Unix:如何删除文件中列出的文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5142429/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Unix: How to delete files listed in a file
提问by Alexander
I have a long text file with list of file masks I want to delete
我有一个长文本文件,其中包含要删除的文件掩码列表
Example:
例子:
/tmp/aaa.jpg
/var/www1/*
/var/www/qwerty.php
I need delete them. Tried rm `cat 1.txt` and it says the list is too long.
我需要删除它们。试过 rm `cat 1.txt`,它说列表太长。
Found this command, but when I check folders from the list, some of them still have files
xargs rm <1.txt
Manual rm call removes files from such folders, so no issue with permissions.
找到了这个命令,但是当我从列表中检查文件夹时,其中一些文件夹仍然有文件
xargs rm <1.txt
Manual rm call 从这些文件夹中删除文件,所以权限没有问题。
回答by Mark Drago
xargs -I{} sh -c 'rm {}' < 1.txt
should do what you want. Be careful with this command as one incorrect entry in that file could cause a lot of trouble.
xargs -I{} sh -c 'rm {}' < 1.txt
应该做你想做的。小心使用此命令,因为该文件中的一个错误条目可能会导致很多麻烦。
This answer was edited after @tdavies pointed out that the original did not do shell expansion.
这个答案是在@tdavies 指出原文没有做 shell 扩展之后被编辑的。
回答by nos
This is not very efficient, but will work if you need glob patterns (as in /var/www/*)
这不是很有效,但如果您需要 glob 模式(如 /var/www/*)
for f in $(cat 1.txt) ; do
rm "$f"
done
If you don't have any patterns and are sure your paths in the file do not contain whitespaces or other weird things, you can use xargs like so:
如果您没有任何模式并且确定文件中的路径不包含空格或其他奇怪的东西,您可以像这样使用 xargs:
xargs rm < 1.txt
回答by tgdavies
You can use this one-liner:
你可以使用这个单线:
cat 1.txt | xargs echo rm | sh
Which does shell expansion but executes rm
the minimum number of times.
哪个进行外壳扩展但执行rm
次数最少。
回答by Chand Priyankara
Here you can use set of folders from deletelist.txtwhile avoiding some patternsas well
在这里,您可以使用文件夹的设置从deletelist.txt,同时避免一些模式,以及
foreach f (cat deletelist.txt)
rm -rf ls | egrep -v "needthisfile|*.cpp|*.h"
end
回答by aks
Assuming that the list of files is in the file 1.txt
, then do:
假设文件列表在 file 中1.txt
,然后执行:
xargs rm -r <1.txt
The -r
option causes recursion into any directories named in 1.txt
.
该-r
选项导致递归到以1.txt
.
If any files are read-only, use the -f
option to force the deletion:
如果任何文件是只读的,请使用该-f
选项强制删除:
xargs rm -rf <1.txt
Be cautious with input to anytool that does programmatic deletions. Make certainthat the files named in the input file are really to be deleted. Be especially careful about seemingly simple typos. For example, if you enter a space between a file and its suffix, it will appear to be two separate file names:
对任何执行程序化删除的工具的输入要谨慎。请一定在输入文件中指定的文件是真的被删除。要特别小心看似简单的错别字。例如,如果在文件及其后缀之间输入一个空格,它将显示为两个单独的文件名:
file .txt
is actually two separate files: file
and .txt
.
实际上是两个单独的文件:file
和.txt
.
This may not seem so dangerous, but if the typo is something like this:
这可能看起来并不那么危险,但如果拼写错误是这样的:
myoldfiles *
Then instead of deleting all files that begin with myoldfiles
, you'll end up deleting myoldfiles
and allnon-dot-files and directories in the current directory. Probably not what you wanted.
然后,而不是删除打头的所有文件myoldfiles
,你最终会删除myoldfiles
和所有的非点的文件和目录在当前目录。可能不是你想要的。
回答by hek2mgl
Use this:
用这个:
while IFS= read -r file ; do rm -- "$file" ; done < delete.list
If you need glob expansion you can omit quoting $file
:
如果您需要 glob 扩展,您可以省略引用$file
:
IFS=""
while read -r file ; do rm -- $file ; done < delete.list
But be warned that file names can contain "problematic" content and I would use the unquoted version. Imagine this pattern in the file
但请注意,文件名可能包含“有问题”的内容,我将使用未引用的版本。想象一下文件中的这种模式
*
*/*
*/*/*
This would delete quite a lot from the current directory! I would encourage you to prepare the delete list in a way that glob patterns aren't required anymore, and then use quotinglike in my first example.
这将从当前目录中删除很多!我鼓励您以不再需要 glob 模式的方式准备删除列表,然后像我的第一个示例一样使用引用。
回答by Evgeni Sergeev
In this particular case, due to the dangers cited in other answers, I would
在这种特殊情况下,由于其他答案中引用的危险,我会
Edit in e.g. Vim and
:%s/\s/\\\0/g
, escaping all space characters with a backslash.Then
:%s/^/rm -rf /
, prepending the command. With-r
you don't have to worry to have directories listed after the files contained therein, and with-f
it won't complain due to missing files or duplicate entries.Run all the commands:
$ source 1.txt
在例如 Vim 和 中编辑,
:%s/\s/\\\0/g
用反斜杠转义所有空格字符。然后
:%s/^/rm -rf /
,在命令之前。随着-r
你不必担心有上市后的文件所载的目录,并用-f
它不会抱怨由于缺少文件或重复的条目。运行所有命令:
$ source 1.txt
回答by nthparameter
Here's another looping example. This one also contains an 'if-statement' as an example of checking to see if the entry is a 'file' (or a 'directory' for example):
这是另一个循环示例。这个还包含一个“if-statement”作为检查条目是否为“文件”(或例如“目录”)的示例:
for f in $(cat 1.txt); do if [ -f $f ]; then rm $f; fi; done
回答by Ray
You could use '\n' for define the new line character as delimiter.
您可以使用 '\n' 将换行符定义为分隔符。
xargs -d '\n' rm < 1.txt
Be careful with the -rf because it can delete what you don't want to if the 1.txt contains paths with spaces. That's why the new line delimiter a bit safer.
小心 -rf 因为如果 1.txt 包含带空格的路径,它可以删除您不想要的内容。这就是为什么新的行分隔符更安全的原因。
On BSD systems, you could use -0 option to use new line characters as delimiter like this:
在 BSD 系统上,您可以使用 -0 选项来使用换行符作为分隔符,如下所示:
xargs -0 rm < 1.txt
回答by Ferroao
This will allow file names to have spaces (reproducible example).
这将允许文件名包含空格(可重现的示例)。
# 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