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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 00:25:38  来源:igfitidea点击:

Unix: How to delete files listed in a file

linuxunix

提问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.txtManual rm call removes files from such folders, so no issue with permissions.

找到了这个命令,但是当我从列表中检查文件夹时,其中一些文件夹仍然有文件 xargs rm <1.txtManual rm call 从这些文件夹中删除文件,所以权限没有问题。

回答by Mark Drago

xargs -I{} sh -c 'rm {}' < 1.txtshould 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 rmthe 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 -roption causes recursion into any directories named in 1.txt.

-r选项导致递归到以1.txt.

If any files are read-only, use the -foption 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: fileand .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 myoldfilesand 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

在这种特殊情况下,由于其他答案中引用的危险,我会

  1. Edit in e.g. Vim and :%s/\s/\\\0/g, escaping all space characters with a backslash.

  2. Then :%s/^/rm -rf /, prepending the command. With -ryou don't have to worry to have directories listed after the files contained therein, and with -fit won't complain due to missing files or duplicate entries.

  3. Run all the commands: $ source 1.txt

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

  2. 然后:%s/^/rm -rf /,在命令之前。随着-r你不必担心有上市后的文件所载的目录,并用-f它不会抱怨由于缺少文件或重复的条目。

  3. 运行所有命令: $ 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