代码之家  ›  专栏  ›  技术社区  ›  EMP

RM无法从脚本中通过通配符删除文件,但在shell提示下工作。

  •  53
  • EMP  · 技术社区  · 15 年前

    我在Linux shell脚本中遇到了一个非常愚蠢的问题。我想删除目录中扩展名为“.bz2”的所有文件。在我调用的脚本中

    rm "$archivedir/*.bz2"
    

    其中$archivedir是目录路径。应该很简单,不是吗?不知何故,它会因以下错误而失败:

    rm: cannot remove `/var/archives/monthly/April/*.bz2': No such file or directory
    

    但那里 目录中名为test.bz2的文件,如果我将脚本更改为

    echo rm "$archivedir/*.bz2"
    

    并将该行的输出复制/粘贴到终端窗口中,文件将被成功删除。我做错什么了?

    6 回复  |  直到 7 年前
        1
  •  99
  •   Abel Callejo    8 年前

    DR

    只引用变量,而不是使用通配符的整个预期路径

    rm "$archivedir"/*.bz2
    

    解释

    • 在UNIX中,程序通常不解释通配符本身。shell解释未加引号的通配符,并用匹配文件名的列表替换每个通配符参数。 如果$archivedir可能包含空格,那么 rm $archivedir/*.bz2 可能不会做你想做的事

    • 您可以通过引用通配符、使用双引号或单引号,或在通配符前面加上反斜杠来禁用此过程。但是,这不是您在这里想要的-您希望通配符扩展到它匹配的文件列表。

    • 注意写作 RM$archivedir/*.bz2 (不带引号)。分词(即将命令行分解为参数)发生 之后 $archivedir被替换。因此,如果$archivedir包含空格,那么您将得到您不想要的额外参数。说阿奇维迪是 /var/archives/monthly/April to June . 那么你就会得到与写作同等的东西 rm /var/archives/monthly/April to June/*.bz2 ,试图删除文件“/var/archives/monthly/april”、“to”,以及所有与“june/*.bz2”匹配的文件,这不是您想要的。

    正确的解决方案是:

    rm "$archivedir"/*.bz2
        2
  •  10
  •   Avery Payne    15 年前

    您的原始行

    rm "$archivedir/*.bz2"
    

    可以重写为

    rm "$archivedir"/*.bz2
    

    达到同样的效果。通配符扩展未在现有设置中正确进行。通过将双引号移到文件路径的“前面”(这是合法的),可以避免这种情况。

        3
  •  9
  •   Jonathan Leffler    15 年前

    为了稍微扩展一下,bash在处理引号中的元字符时有相当复杂的规则。一般来说

    • 几乎没有什么可以用单引号解释:

       echo '$foo/*.c'                  => $foo/*.c
       echo '\\*'                       => \\*
      
    • 外壳替换在双引号内完成,但文件元字符未展开:

       FOO=hello; echo "$foo/*.c"       => hello/*.c
      
    • 后引号中的所有内容都被传递到解释它们的子shell。未导出的shell变量未在子shell中定义。所以,第一个命令的回声是空白的,但第二个和第三个回声是“再见”:

      BAR=bye echo `echo $BAR`
      BAR=bye; echo `echo $BAR`
      export BAR=bye; echo `echo $BAR`
      

    (把这个印成你想要的样子,所以 尝试了几次 显然是不可能的……)

        4
  •  4
  •   Brian Gianforcaro    15 年前

    引号导致字符串被解释为字符串文字,请尝试删除它们。

        5
  •  0
  •   Christo    13 年前

    我在调用shell脚本时看到类似的错误 /shell脚本.sh 来自另一个shell脚本。这可以通过调用它来修复 sh shell_script.sh脚本

        6
  •  0
  •   holms    7 年前

    为什么不只是 rm -rf */*.bz2 ?在OSX上为我工作。