BASH:如何删除除清单中命名的文件之外的所有文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2782602/
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
BASH: How to remove all files except those named in a manifest?
提问by brice
I have a manifest file which is just a list of newline separated filenames. How can I remove all files that are notnamed in the manifest from a folder?
我有一个清单文件,它只是一个以换行符分隔的文件名列表。如何从文件夹中删除清单中未命名的所有文件?
I've tried to build a find ./ ! -name "filename"command dynamically:
我尝试find ./ ! -name "filename"动态构建命令:
command="find ./ ! -name \"MANIFEST\" "
for line in `cat MANIFEST`; do
command=${command}"! -name \"${line}\" "
done
command=${command} -exec echo {} \;
$command
But the files remain.
但文件仍然存在。
[Note:] I know this uses echo. I want to check what my command does before using it.
[注意:] 我知道这使用回声。我想在使用它之前检查我的命令做了什么。
Solution:(thanks PixelBeat)
解决方案:(感谢PixelBeat)
ls -1 > ALLFILES
sort MANIFEST MANIFEST ALLFILES | uniq -u | xargs rm
Without temp file:
没有临时文件:
ls -1 | sort MANIFEST MANIFEST - | uniq -u | xargs rm
Both Ignores whether the files are sorted/not.
两者 忽略文件是否已排序/未排序。
采纳答案by pixelbeat
Using the "set difference" pattern from http://www.pixelbeat.org/cmdline.html#sets
使用来自http://www.pixelbeat.org/cmdline.html#sets的“设置差异”模式
(find ./ -type f -printf "%P\n"; cat MANIFEST MANIFEST; echo MANIFEST) |
sort | uniq -u | xargs -r rm
Note I list MANIFEST twice in case there are files listed there that are not actually present. Also note the above supports files in subdirectories
注意我列出 MANIFEST 两次,以防其中列出的文件实际上并不存在。另请注意上述支持子目录中的文件
回答by Jürgen H?tzel
For each filein current directory grepfilename in MANIFEST file and rmfileif not matched.
对于当前目录中的每个文件,清单文件中的grep文件名和rm文件(如果不匹配)。
for file in *
do grep -q -F "$file" PATH_TO_YOUR_MANIFIST || rm "$file"
done
回答by brice
figured it out:
弄清楚了:
ls -1 > ALLFILES
comm -3 MANIFEST ALLFILES | xargs rm
回答by DVK
Just for fun, a Perl 1-liner... not really needed in this case but much more customizable/extensible than Bash if you want something fancier :)
只是为了好玩,Perl 1-liner ......在这种情况下并不是真的需要,但如果你想要更高级的东西,它比 Bash 更可定制/可扩展:)
$ ls
1 2 3 4 5 M
$ cat M
1
3
$ perl -e '{use File::Slurp; %M = map {chomp; $_ => 1} read_file("M"); $M{M}=1; \
foreach $f (glob("*")) {next if $M{$f}; unlink "$f"||die "Can not unlink: $!\n" };}'
$ ls
1 3 M
The above can be even shorter if you pass the manifest on STDIN
如果您在 STDIN 上传递清单,则上述内容甚至可以更短
perl -e '{%M = map {chomp; $_ => 1} <>; $M{M}=1; \
foreach $f (glob("*")) {next if $M{$f};unlink "$f"||die "Can not unlink: $!\n" };}' M
回答by Paused until further notice.
Assumes that MANIFEST is already sorted:
假设 MANIFEST 已经排序:
find -type f -printf %P\n | sort | comm -3 MANIFEST - | xargs rm

