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


91

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

例:

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

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

找到了此命令,但是当我从列表中检查文件夹时,其中某些文件夹仍包含文件。 xargs rm <1.txt手动rm调用可从此类文件夹中删除文件,因此权限没有问题。


8
即使六年之后:您是否会接受答案之一?这会将问题标记为已解决,也可以帮助其他用户。
MERose

Answers:


113

这不是很有效,但是在需要全局模式时可以使用(如/ var / www / *)

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

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

xargs rm < 1.txt

4
如果路径包含空格,第一个解决方案(使用CAT)将如何处理?
a.dibacco,

57

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

xargs rm -r <1.txt

-r选项将导致递归到以下任何目录中1.txt

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

xargs rm -rf <1.txt

请谨慎输入执行程序删除的任何工具。请一定在输入文件中指定的文件是真的被删除。特别注意看似简单的错别字。例如,如果在文件及其后缀之间输入一个空格,它将显示为两个单独的文件名:

file .txt

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

这似乎并不那么危险,但是如果输入错误是这样的:

myoldfiles *

然后,而不是删除打头的所有文件myoldfiles,你最终会删除myoldfiles所有的非点的文件和目录在当前目录。可能不是您想要的。


1
-rf对“ myoldfiles /”或“ / tmp”造成更大的破坏。注意“ /”旁边的空格字符。

23

用这个:

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

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

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

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

*
*/*
*/*/*

这将从当前目录中删除很多内容!我鼓励您以不再需要全局模式的方式准备删除列表,然后像在我的第一个示例中一样使用引号


3
目前,这是处理所有,的唯一答案/My Dir With Spaces/ /Spaces and globs/*.txt,此外--file-with-leading-dashes,它是POSIX,可在GNU / Linux,macOS和BSD上运行。
另一个人

17

您可以使用“ \ n”将换行符定义为定界符。

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

注意-rf,因为如果1.txt包含带空格的路径,它会删除您不需要的内容。这就是为什么新行分隔符更安全的原因。

在BSD系统上,可以使用-0选项将换行符用作分隔符,如下所示:

xargs -0 rm < 1.txt

1
在OS X上,这让我xargs: illegal option -- d
waldyrious

好点子。似乎没有其他选择比-0在OS X
射线

2
xargs -I_ rm _也可以在OS X中使用:)请参见stackoverflow.com/a/39335402/266309
waldyrious

如果使用BSD xargs(没有-d),则可以先将换行符转换为null:tr '\n' '\0' < 1.txt | xargs -0 rm
OrangeDog

13

您可以使用这种单线:

cat 1.txt | xargs echo rm | sh

进行外壳扩展,但执行rm最少次数。


只要扩展时间不长?
道格拉斯·里德

1
诚然,一个glob可能会产生一个过长的参数列表-您可以添加该-n <n>参数以xargs减少传递给每个rm的参数的数量,但是仍然不能保护您免受单个glob的限制。
tgdavies 2011年

13

xargs -I{} sh -c 'rm {}' < 1.txt应该做你想做的。请谨慎使用此命令,因为该文件中的一个错误条目可能会引起很多麻烦。

在@tdavies指出原始文件没有进行shell扩展之后,对该答案进行了编辑。


谢谢,但不需要删除文件夹,只需删除文件
Alexander

2
这些球不会扩展,因为它们不会被外壳“看到”。
tgdavies 2011年

@tdavies哇-你是对的。该命令(尽管有点难看)将起作用:xargs -I{} sh -c 'rm {}' < 1.txt
Mark Drago

4

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

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

  2. 然后:%s/^/rm -rf /,在命令之前。有了-r您,您不必担心在其中包含的文件之后列出目录,并且-f不会因缺少文件或重复条目而抱怨。

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


空格不是唯一需要转义的字符,在文件名中也很流行,也是任何类型的方括号,都可能导致不必要的扩展。
emk2203 '19

4

cat 1.txt | xargs rm -f | bash 运行命令将仅对文件执行以下操作。

cat 1.txt | xargs rm -rf | bash 运行命令将执行以下递归行为。


2

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

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

1

这是另一个循环的例子。此示例还包含一个“ if语句”,作为检查条目是否为“文件”(例如,“目录”)的示例:

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

0

在这里,您可以使用文件夹的设置从deletelist.txt,同时避免一些模式,以及

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

0

这将允许文件名包含空格(可重现的示例)。

# 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

0

万一有人喜欢sed并删除而没有通配符扩展

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

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

为了完整起见,与awk

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

如果除去单引号,通配符扩展将起作用,但是如果文件名包含空格,这将很危险。这将需要在通配符周围添加引号。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.