我有一个清单文件,它只是换行符分隔的文件名列表。如何从文件夹中删除清单中不所有文件?
我尝试动态构建find ./ ! -name "filename"
命令:
command="find ./ ! -name \"MANIFEST\" "
for line in `cat MANIFEST`; do
command=${command}"! -name \"${line}\" "
done
command=${command} -exec echo {} \;
$command
但文件仍然存在。
[注意:]我知道这使用echo。我想在使用之前检查一下我的命令。
解决方案:(感谢PixelBeat)
ls -1 > ALLFILES
sort MANIFEST MANIFEST ALLFILES | uniq -u | xargs rm
没有临时文件:
ls -1 | sort MANIFEST MANIFEST - | uniq -u | xargs rm
两者都忽略文件是否已排序。
答案 0 :(得分:14)
对于MANIFEST文件中当前目录 grep 文件名中的每个文件,如果不匹配则 rm 文件。< / p>
for file in *
do grep -q -F "$file" PATH_TO_YOUR_MANIFIST || rm "$file"
done
答案 1 :(得分:13)
使用http://www.pixelbeat.org/cmdline.html#sets
中的“设置差异”模式(find ./ -type f -printf "%P\n"; cat MANIFEST MANIFEST; echo MANIFEST) |
sort | uniq -u | xargs -r rm
注意我列出两次MANIFEST,以防其中列出的文件实际上不存在。 另请注意,上面支持子目录中的文件
答案 2 :(得分:5)
想通了:
ls -1 > ALLFILES
comm -3 MANIFEST ALLFILES | xargs rm
答案 3 :(得分:1)
只是为了好玩,一个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
如果你在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
答案 4 :(得分:0)
假设MANIFEST已经排序:
find -type f -printf %P\\n | sort | comm -3 MANIFEST - | xargs rm