Unix命令删除了所有目录,尽管没有指定删除所有目录的操作

5

我是一个对Unix非常陌生的新手。我运行了以下命令。

ls -l | xargs rm -rf bark.*

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

有人能解释一下为什么吗?

3个回答

10
-r参数意味着“递归删除”(即进入子目录)。-f命令表示“强制”(换句话说,不要请求确认)。-rf表示“递归进入子目录而不需要确认”。 ls -l列出目录中的所有文件。xargs获取来自ls -l的输入并将其附加到您传递给xargs的命令后面。
最终执行的命令看起来像这样:
rm -rf bark.* <output of ls -l>

这基本上删除了bark.*和当前目录中的所有文件。故事的寓意是:使用rm -rf时要非常小心。(您可以使用rm -ri在删除文件之前询问是否确定)


6
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 可能是其中一个残缺不全的白痴系统。 - tchrist

5

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”字符开头的文件,忽略大写字母/小写字母/大小写混合,并将它们删除”。如果您有拼写错误,这仍然可能是一个糟糕的命令,因此在进行此类批量删除之前,应始终进行测试以确保它们是您要删除的文件。

在将来,首先执行以下操作以获取要删除的所有文件的列表,以确认它们是您要删除的文件。
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 文件/文件夹名称中有一个空格字符)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接