【问题标题】:Unix command deleted every directory even though not specifiedUnix 命令删除了每个目录,即使没有指定
【发布时间】:2012-05-19 14:09:03
【问题描述】:

我对 unix 很陌生。我运行了以下命令。

ls -l | xargs rm -rf bark.*

及以上命令删除了文件夹中的每个目录。

谁能解释我为什么?

【问题讨论】:

    标签: linux bash unix xargs rm


    【解决方案1】:

    -r 参数表示“递归删除”(即下降到子目录)。 -f 命令的意思是“强制”(换句话说,不要求确认)。 -rf 表示“递归下降到子目录而不要求确认”

    ls -l 列出目录中的所有文件。 xargsls -l 获取输入并将其附加到您传递给 xargs 的命令中

    最终执行的命令如下所示:

    rm -rf bark.* <output of ls -l>
    

    这实际上删除了bark.* 当前目录中的所有文件。故事的寓意:小心rm -rf。 (删除文件前可以使用rm -ri询问)

    【讨论】:

      【解决方案2】:

      rm(1) 删除了当前工作目录中的所有文件和目录,因为您要求它这样做。

      要大致了解发生了什么,请运行以下命令:

      cd /etc ;  ls -l | xargs echo
      

      注意输出。

      我强烈建议在构建命令行时使用echo 代替rm -rf。只有当输出看起来不错时,您才应该使用rm -rf 重新运行该命令。如有疑问,也许只需使用rm -r,这样您就不会意外吹走太多。 rm -ir 如果您非常对命令行持怀疑态度。 (我从 1994 年开始使用 Linux,仍然在构建稍微复杂的命令行以选择性地删除一堆文件时使用这个 echo 技巧。)

      顺便说一句,我会避免以任何方式解析 ls(1) 输出——文件名可以包含 任何 字符,除了 ASCII NUL/ 字符——包括换行符、制表符和输出看起来ls -l 输出。尝试使用诸如 xargs(1) 之类的工具解析这个可能很危险。

      相反,使用find(1) 处理这类事情。要删除所有名为bark.* 的目录中的所有文件,我会运行如下命令:

      find . -type d -name 'bark.*' -print0 | xargs -0 rm -r
      

      再次,我将使用echo 代替rm -r 进行第一次执行——如果它看起来不错,那么我将使用rm -r 重新运行。

      【讨论】:

      • 有时我发现自己在没有find -print0 和配对xargs -0 的系统上。非常非常烦人。我认为 Solaris 可能就是这样一个残废的白痴。
      【解决方案3】:

      ls -l 命令给出了当前工作目录 (PWD) 中所有子目录的列表。

      rm 命令可以删除多个文件/目录,如果您将它们作为列表传递给它。

      例如:rm test1.txt test2.txt myApp 将删除所有三个具有名称的文件:

      test1.txt
      test2.txt
      myApp
      

      此外,您使用的 rm 命令的标志在许多愚蠢行为中很常见。
      rm -f - 无需询问或确认即可强制删除文件
      rm -r - 递归到所有子目录并删除它们的所有内容和子目录

      所以,假设你在 /home/user,目录结构如下:

       /home/user
      |->dir1
      |->dir2
      `->file1.txt
      

      ls -l 命令将提供包含"dir1 dir2 file1.txt" 的列表,命令ls -l | xargs rm -rf 的结果将如下所示:
      rm -rf dir1 dir2 file1.txt

      如果我们使用上面的示例扩展您的原始问题,传递给系统的最终命令将变为: rm -rf di1 dir2 file1.txt bark.*

      因此,当前目录中的所有内容都会被清除,因此 bark.* 是多余的(您实际上是告诉机器无论如何都要销毁当前目录中的所有内容)。

      我认为您的意思是删除当前目录中的所有文件以及以bark. 开头的所有子目录(递归)要做到这一点,您只需要这样做:
      find -iname bark.* | xargs rm

      上面的命令的意思是“在这个目录和子目录中查找所有以“bark.”开头的文件,忽略大写/小写/mIxEdCaSe,并删除它们”。如果您有错字,这仍然可能是一个错误的命令,因此可以肯定的是,在执行这样的批量删除之前,您应该始终进行测试。

      以后,请先执行以下操作以获取您将首先删除的所有文件的列表,以确认它们是您要删除的文件。
      find -iname bark.* | xargs echo

      如果您确定,请通过
      find -iname bark.* | xargs rm

      删除它们

      希望这会有所帮助。

      作为一个幽默的注释,可以在这里找到最著名的“rm -rf”实例之一: https://github.com/MrMEEE/bumblebee-Old-and-abbandoned/commit/a047be85247755cdbe0acce6f1dafc8beb84f2ac

      一个自动化脚本运行类似rm -rf /usr/local/.........的东西,但是由于不小心插入了一个空格,命令变成了rm -rf /usr /local/......,所以这实际上意味着“删除所有以usr或local开头的根文件夹”,有效地破坏了系统任何使用它的人。我为那个开发者感到难过。

      您可以通过引用您的字符串来避免这些类型的错误,即: rm -rf "/usr/ local/...." 会提供一条错误消息并避免此错误,因为引号意味着它们之间的所有内容都是完整路径,而不是单独路径/文件的列表(即:您告诉 rm 文件/文件夹有一个空格名称中的字符)。

      【讨论】:

        猜你喜欢
        • 2017-03-28
        • 1970-01-01
        • 2011-05-23
        • 2021-05-06
        • 2012-12-25
        • 2021-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多