【问题标题】:Glob-like brace Wildcards in BashBash 中类似 Glob 的大括号通配符
【发布时间】:2012-11-23 21:22:24
【问题描述】:

假设我有一个目录/etc/php5/conf.d/,其中包含以下假设文件:

mysql.ini
mysqli.ini
20-mysql.ini
20-mysqli.ini
20-pdo_mysql.ini

我想删除除最后一个 (pdo) 之外的所有这些文件,这是我目前拥有的:

for phpIni in mysql mysqli; do
    if [[ -f /etc/php5/conf.d/$phpIni.ini ]]; then
        rm /etc/php5/conf.d/$phpIni.ini
    if [[ -f /etc/php5/conf.d/20-$phpIni.ini ]]; then
        rm /etc/php5/conf.d/20-$phpIni.ini
    fi
done

它有效,但我不禁注意到上面可以用 glob 模式简化,例如:

if [[ ! -z /etc/php5/conf.d/{,20-}mysql*ini ]]; then
    rm /etc/php5/conf.d/{,20-}mysql*ini
fi

但是有一个问题,如果任何扩展不存在,rm 会抱怨它:

$ if [[ ! -z /etc/php5/conf.d/{,20-}mysql*ini ]]; then rm /etc/php5/conf.d/{,20-}mysql*ini; fi
rm: cannot remove `/etc/php5/conf.d/20-mysql*ini': No such file or directory

如何让 rm 只删除现有文件?或者至少防止它抛出所有这些错误?

【问题讨论】:

  • if 测试不会做你想做的事。 [[ ! -z /etc/php5/conf.d/{,20-}mysql*ini ]] 始终为真,无论是否存在与该模式匹配的任何文件。我认为这是因为 bash 在这种情况下不进行模式匹配,但即使这样做了它仍然无法工作,因为未匹配的模式未展开(除非您先执行 shopt -s nullglob)。
  • @GordonDavisson:我使用echo 而不是rm 命令对其进行了测试,它似乎只在至少一个文件存在时才回显字符串。我错过了什么吗?
  • 很奇怪;它总是为我执行echo(尽管如果设置了nullglob,echo 只会打印一个空行)。您使用的是哪个版本的 bash?我有 3.2.48(1)-release。
  • @GordonDavisson:我使用的是 Ubuntu 12.04.1 LTS 附带的 4.2.24(1)-release。无论如何我可以确认shopt的当前状态标志吗?
  • shopt nullglob 将打印其当前状态(shopt 将单独打印所有可设置选项的状态)。

标签: bash list conditional-statements glob rm


【解决方案1】:

您可以使用rm -f,如果文件不存在,它不会报错:如手册页所示, “忽略不存在的文件,从不提示”。

【讨论】:

  • 我确实阅读了手册页,但不知何故我的眼睛错过了 f 标志...谢谢!
【解决方案2】:

添加 -f 作为 rm 参数将防止这种情况发生。但另一方面,您需要确保您的 glob 是可靠的,以免删除太多。

【讨论】:

  • 谢谢,我测试了它,我认为它可以满足我的需求。无论哪种方式,这些都只是符号链接。
【解决方案3】:

添加shopt -s nullglob -- 如果没有匹配模式的文件,则替换空字符串而不是模式字符串。

要删除除一个以外的所有内容,请使用

shopt -s extglob
rm !(*pdo*).ini

【讨论】:

  • 谢谢,这是一个巧妙的技巧!不幸的是,它不起作用,因为我还有更多要保留的.ini 文件。关于shopt,您介意阅读我留给@GordonDavisson 的评论吗?
  • 请在您的问题中提供更多详细信息。我不知道你的担心是什么
猜你喜欢
  • 1970-01-01
  • 2014-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-11
  • 2013-05-27
  • 2015-03-04
相关资源
最近更新 更多