Unix: How to delete files listed in a file

我有一个很长的文本文件,其中包含要删除的文件掩码列表

例如:

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

我需要删除它们。尝试了 rm 1.txt & # x60; 它说这个列表太长了。

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

163514 次浏览

xargs -I{} sh -c 'rm "{}"' < 1.txt应该做你想做的。小心使用这个命令,因为该文件中的一个错误条目可能会导致很多麻烦。

这个答案是在@tdavies 指出原来没有做 shell 扩展之后编辑的。

这不是非常有效,但是如果需要 globb 模式(如/var/www/*) ,则可以使用它

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

如果您没有任何模式,并确保文件中的路径不包含空格或其他奇怪的东西,您可以使用 xargs,如下所示:

xargs rm < 1.txt

你可以用这个俏皮话:

cat 1.txt | xargs echo rm | sh

Which does shell expansion but executes rm the minimum number of times.

在这里,你可以使用从 Deletelist.txt的文件夹集,而 避免某些模式以及

foreach f (cat deletelist.txt)
rm -rf ls | egrep -v "needthisfile|*.cpp|*.h"
end

假设文件列表在文件 1.txt中,然后执行:

xargs rm -r <1.txt

-r选项使递归进入 1.txt中命名的任何目录。

If any files are read-only, use the -f option to force the deletion:

xargs rm -rf <1.txt

对于输入进行编程删除的 any工具,请谨慎使用。使 当然输入文件中命名的文件真正被删除。特别要注意看似简单的拼写错误。例如,如果您在一个文件及其后缀之间输入一个空格,它将显示为两个独立的文件名:

file .txt

实际上是两个独立的文件: file.txt

这可能看起来不那么危险,但如果打印错误是这样的:

myoldfiles *

然后不是删除所有以 myoldfiles开头的文件,而是删除工作目录中的 myoldfiles所有非点文件和目录。可能不是你想要的。

用这个:

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

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

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

但请注意,文件名可能包含“有问题的”内容,我将使用未引用的版本。想象一下文件中的这个模式

*
*/*
*/*/*

这会从工作目录中删除很多内容!我建议您准备删除列表的方式不再需要通配符模式,然后像我的第一个示例那样准备 引用

在这个特殊的情况下,由于其他答案中提到的危险,我会

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

  2. 然后 :%s/^/rm -rf /,在命令之前。使用 -r时,您不必担心在其中包含的文件之后列出目录,而使用 -f时,它不会因为文件丢失或重复条目而抱怨。

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

下面是另一个循环示例。这个例子还包含一个“ if 语句”作为检查条目是否是“ file”(或者是“目录”)的例子:

for f in $(cat 1.txt); do if [ -f $f ]; then rm $f; fi; done

可以使用’n’将新行字符定义为分隔符。

xargs -d '\n' rm < 1.txt

小心使用-rf,因为如果1.txt 包含带空格的路径,它可能会删除您不想删除的内容。这就是为什么新的行分隔符更安全一些。

在 BSD 系统中,您可以使用 -0选项来使用新的行字符作为分隔符,如下所示:

xargs -0 rm < 1.txt

这将允许文件名使用空格(可重复的示例)。

# Select files of interest, here, only text files for ex.
find -type f -exec file {} \; > findresult.txt
grep ": ASCII text$" findresult.txt > textfiles.txt
# leave only the path to the file removing suffix and prefix
sed -i -e 's/:.*$//' textfiles.txt
sed -i -e 's/\.\///' textfiles.txt


#write a script that deletes the files in textfiles.txt
IFS_backup=$IFS
IFS=$(echo "\n\b")
for f in $(cat textfiles.txt);
do
rm "$f";
done
IFS=$IFS_backup


# save script as "some.sh" and run: sh some.sh

运行该命令将仅针对文件执行以下操作。

cat 1.txt | xargs rm -rf | bash Run the command will do the following recursive behaviour.

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

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

如果有人更喜欢 sed而去掉 没有通配符扩展:

sed -e "s/^\(.*\)$/rm -f -- \'\1\'/" deletelist.txt | /bin/sh

提醒: 在文件中使用绝对路径名,或者确保位于正确的目录中。

为了完整起见,awk也是如此:

awk '{printf "rm -f -- '\''%s'\''\n",$1}' deletelist.txt | /bin/sh

如果单引号被删除,通配符扩展将会工作,但是如果文件名包含空格,这是危险的。这需要在通配符周围添加引号。