Unix:如何删除在文件中列出的文件

127

我有一个包含要删除的文件名通配符列表的长文本文件。

例如:

/tmp/aaa.jpg
/var/www1/*
/var/www/qwerty.php

我需要删除它们。尝试使用rm `cat 1.txt`,但显示列表太长。

找到了这个命令,但是当我检查列表中的文件夹时,其中一些仍然有文件。 xargs rm <1.txt手动使用rm从这些文件夹中删除文件,因此权限没有问题。


16
虽然已经过去六年了,你介意接受其中一个答案吗?这将标记问题已解决,并帮助其他用户。 - MERose
13个回答

153

这并不是非常高效的方法,但如果你需要使用类似于 /var/www/* 的通配符模式,则可行。

for f in $(cat 1.txt) ; do 
  rm "$f"
done

如果您没有任何模式,并且确定文件中的路径不包含空格或其他奇怪的字符,则可以使用xargs进行操作,如下所示:

xargs rm < 1.txt

5
如果路径中包含空格,第一个解决方案(使用CAT)会发生什么? - a.dibacco
1
使用包含空格路径的文本文件时,这在我使用MINGW64 Bash上没有起作用。 - 804b18f832fb419fb142
@804b18f832fb419fb142 是的,我也一样。有其他选择吗? - a06e
为了处理空白处,我建议使用一个带有读取函数的while循环来解决这个问题。一个脚本可以是filename='123.txt'; while read line ; rm -r "$line"; done < $filename。请注意在$line周围的引号。这是shell脚本中的一个要点。 - undefined

77

假设文件列表在文件1.txt中,则执行以下操作:

xargs rm -r <1.txt

-r选项会使得进入1.txt中所有命名的目录进行递归操作。

如果有任何只读文件,使用-f选项来强制删除:

xargs rm -rf <1.txt

使用任何进行编程删除的工具时,请小心输入。确保在输入文件中命名的文件确实要被删除。特别注意看似简单的打字错误。例如,如果您在文件名和后缀之间输入一个空格,则它将显示为两个不同的文件名:


file .txt

实际上是两个不同的文件:file.txt

这可能看起来并不危险,但如果打错了字如下所示:

myoldfiles *

那么,如果你删除所有以myoldfiles开头的文件,最终你将会删除当前目录下myoldfiles文件和所有非点文件和目录。这可能不是你想要的结果。


1
"myoldfiles /" 或者 "/ tmp" 加上 -rf 更加危险。请注意斜杠后面的空格字符。 - Ray
2
我认为这是一个危险的答案,如果它是一个文件列表,为什么要使用递归,再加上强制删除,这会成为一个“踏板枪”。 - CervEd
@CervEd 因为有时候一个人需要自己给自己开枪,才能完成任务。 - Joshua Jurgensmeier

31

使用这个:

while IFS= read -r file ; do rm -- "$file" ; done < delete.list

如果你需要全局扩展,可以省略引用$file

IFS=""
while read -r file ; do rm -- $file ; done < delete.list

但请注意文件名可能包含“有问题”的内容,建议使用未加引号的版本。想象一下文件中出现了这种模式

*
*/*
*/*/*

这将从当前目录中删除相当多的内容!我建议您以一种不再需要使用glob模式的方式准备删除列表,然后像我的第一个示例那样使用引号


4
目前这是唯一一个能够处理所有/My Dir With Spaces/ /Spaces and globs/*.txt, --file-with-leading-dashes的答案,额外加分点是它遵循 POSIX,适用于GNU/Linux、macOS和BSD。 - that other guy

20
你可以使用 '\n' 作为换行符来定义分隔符。
xargs -d '\n' rm < 1.txt

当使用 -rf 命令时要小心,因为如果 1.txt 文件包含带空格的路径,它可能会删除你不想删除的内容。这就是为什么换行符作为分隔符更安全一些。

在 BSD 系统上,你可以使用 -0 选项来使用新行字符作为分隔符,像这样:

xargs -0 rm < 1.txt

1
在OS X上,这会让我得到“xargs:非法选项--d”。 - waldyrious
2
xargs -I_ rm _ 在 OS X 中也可以使用 :) 参见 https://dev59.com/mm3Xa4cB1Zd3GeqPbB67#39335402 - waldyrious
2
你也可以先运行 xargs -d '\n' ls < 1.txt 或者 xargs -d '\n' stat < 1.txt 来验证将要被删除的内容,以避免不必要的意外。 - CervEd
@CervEd 好主意。我通常会这样做:xargs -d '\n' echo rm < 1.txt - Ray
1
使用stat或find命令,如果文件不存在、没有权限等会出现错误,这对于验证路径是否正确非常有帮助。 - CervEd
显示剩余2条评论

20

xargs -I{} sh -c 'rm "{}"' < 1.txt 可以实现您想要的功能。但要小心使用此命令,因为文件中一个错误的条目可能会引起很多麻烦。

在 @tdavies 指出原始文本没有执行 shell 扩展后,此答案经过了编辑。


谢谢,但不需要删除文件夹,只需删除文件。 - Alexander
2
通配符不会被展开,因为它们从未被 shell“看到”。 - tgdavies
@tdavies 惊人!你说得对。这个命令(虽然有点丑)可以工作:xargs -I{} sh -c 'rm {}' < 1.txt - Mark Drago
如果文件名包含单引号,则无法正常工作。 - CervEd
现在它也支持空格。 - Sebastian Barth

18

你可以使用这个一行代码:

cat 1.txt | xargs echo rm | sh

该命令会进行Shell扩展,但最少执行rm的次数。


只要任何扩展不太长? - Douglas Leeder
1
True,一个glob可能会产生一个太长的参数列表--你可以添加xargs-n <n>参数来减少传递给每个rm的参数数量,但这仍然不能保护你免受超过限制的单个glob的影响。 - tgdavies

8

为了提供另一种方法,您也可以简单地使用以下命令

$ cat to_remove
/tmp/file1
/tmp/file2
/tmp/file3
$ rm $( cat to_remove )

1
运行得非常好,即使使用 rm -r 命令也是如此。以这种方式删除了约 5TB 的数据。也可以与其他命令一起使用,例如 lsdu - Ólavur
路径中有空格怎么办? - CervEd

5

cat 1.txt | xargs rm -f | bash 运行此命令将只对文件进行操作。

cat 1.txt | xargs rm -rf | bash 运行此命令将会进行递归操作。


4

鉴于其他答案中提到的危险性,在这种特殊情况下,我建议:

  1. 使用例如Vim进行编辑,运行命令:%s/\s/\\\0/g,将所有空格字符用反斜杠转义。

  2. 然后运行命令:%s/^/rm -rf /,在命令前添加删除命令。使用-r选项可以避免出现文件夹列表中包含其中的文件,而使用-f选项可以避免因缺少文件或重复条目而发出投诉。

  3. 运行所有命令:$ source 1.txt


空格不是唯一需要转义的字符,文件名中常见的括号也可能导致意外扩展。 - emk2203

1
以下是另一个循环示例。这个示例还包含一个“if语句”,用于检查输入是否为“文件”(或者例如一个“目录”):
for f in $(cat 1.txt); do if [ -f $f ]; then rm $f; fi; done

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