【问题标题】:Match backed up files (`*~`)匹配备份文件 (`*~`)
【发布时间】:2014-02-18 14:11:51
【问题描述】:

我正在尝试匹配脚本中的备份文件,然后将其删除。备份文件中包含波浪号 (~):

$ ls -al
drwxr-xr-x 3 jwalton jwalton 4096 Feb 18 09:00 .
drwxr-xr-x 5 jwalton jwalton 4096 Feb 18 08:54 ..
drwxr-xr-x 5 jwalton jwalton 4096 Feb 18 08:54 test-proj
-rwxr-xr-x 1 jwalton jwalton  664 Feb 18 09:00 clean.sh
-rwxr-xr-x 1 jwalton jwalton  628 Feb 18 08:59 clean.sh~

我的干净脚本有以下测试,但看起来我做错了什么:

if [ -e "*~" ]; then
  rm "*~"
fi

匹配备份文件的正确测试是什么?

【问题讨论】:

  • 例如,将rm 替换为ls 进行测试。

标签: regex bash match filenames


【解决方案1】:

你不需要测试它。 rm -f(忽略不存在的文件)将完成这项工作。

rm -f *~

在引号内,* 匹配 * 字面意思:

例子:

$ ls
*~  a  a~
$ ls *~
*~  a~
$ ls "*~"
*~

【讨论】:

  • 感谢 falsetru。我首先尝试匹配它的原因是避免出现“*~ not found”错误消息。
  • @noloader,如果你使用-f 选项,rm 不会输出错误。
  • 这是因为~没有在双引号内展开。
  • @fedorqui,也许你的意思是*~ 扩展到主目录(仅当单词以它开头时)
  • @fedorqui,根据 bash(1),波浪号扩展如果单词以不带引号的波浪号字符 (~) 开头,第一个不带引号的斜杠之前的所有字符(或所有字符,如果没有不带引号的斜杠)都被视为波浪号前缀。 ....
【解决方案2】:

是你的报价搞砸了。它正在寻找一个字面上称为*~ 的文件。这有效,但前提是 *~ 恰好扩展到一个文件::

if [ -e *~ ]; then
   rm *~
fi

为什么?因为shell 扩展了通配符first。所以如果不匹配,就相当于:

if [ -e ]; then  // false positive!

如果匹配一个文件x.txt~,则扩展为:

if [ -e x.txt~ ]; then // OK

如果匹配多个文件x.txt~ y.txt~,则扩展为:

if [ -e x.txt~ y.txt~ ]; then // "[: x.txt~: binary operator expected"

值得知道的是,UNIX 文件名可以包含除/ 和 ASCII 0 之外的任何字符。所以你可以这样做:

 $ touch "*~"
 $ ls "*~"
 *~
 $ rm "*~"

您最终可能会得到带有尴尬名称的文件,例如 -r

 $ touch -- -r  # or imagine, your own C, Java etc. program
 $ ls
 -r
 $ rm -- -r

但是,if 并不是必需的。它只是为了防止ls 给出No such file or directory 错误,您可以通过以下方式抑制这些错误:

rm -f *~

【讨论】:

  • [ -e *~ ] 仅在模式扩展到一个文件时才有效;否则,您将收到有关预期二元运算符的错误。
【解决方案3】:

我猜使用 find 是最好的:

find ./ -name "*~" -exec rm {} \; 

【讨论】:

  • find . -name "*~" -print | xargs rm -f - 效率稍高。
  • find . -name "*~" -delete - 效率更高
【解决方案4】:

如果你想递归地进入子目录:

shopt -s globstar nullglob
rm **~

【讨论】:

    猜你喜欢
    • 2015-04-18
    • 1970-01-01
    • 1970-01-01
    • 2011-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-02
    相关资源
    最近更新 更多