【问题标题】:BASH: How to remove all files except those named in a manifest?BASH:如何删除除清单中命名的文件之外的所有文件?
【发布时间】:2011-02-16 11:27:58
【问题描述】:

我有一个清单文件,它只是一个以换行符分隔的文件名列表。如何从文件夹中删除清单中命名的所有文件?

我尝试动态构建find ./ ! -name "filename" 命令:

command="find ./ ! -name \"MANIFEST\" "
for line in `cat MANIFEST`; do
    command=${command}"! -name \"${line}\" " 
done
command=${command} -exec echo {} \;
$command

但文件仍然存在。

[注意:] 我知道这使用回声。我想在使用它之前检查我的命令的作用。

解决方案:(感谢PixelBeat

ls -1 > ALLFILES
sort MANIFEST MANIFEST ALLFILES | uniq -u | xargs rm

没有临时文件:

ls -1 | sort MANIFEST MANIFEST - | uniq -u | xargs rm

两者都忽略文件是否已排序。

【问题讨论】:

  • 谢谢大家!我将它提供给 pixelbeat,以获取他的解决方案的 shell 指南

标签: bash unix scripting find


【解决方案1】:

使用来自http://www.pixelbeat.org/cmdline.html#sets的“设置差异”模式

(find ./ -type f -printf "%P\n"; cat MANIFEST MANIFEST; echo MANIFEST) |
  sort | uniq -u | xargs -r rm

注意我列出了两次清单,以防列出的文件实际上不存在。 还要注意上面支持子目录中的文件

【讨论】:

  • 我收到了rm: missing operand 的命令。我只是使用 ls、comm 和 xargs 解决了这个问题。无论如何谢谢pb
  • 向 xargs 添加 -r 以删除该警告(当不需要删除任何文件时)
  • 使用grep设置差异模式:find ./ -type f -printf "%P\n" | fgrep -vf MANIFEST |...
【解决方案2】:

对于当前目录中的每个 file grep MANIFEST 文件中的文件名和 rm file 如果不匹配。

for file in *
  do grep -q -F "$file" PATH_TO_YOUR_MANIFIST ||  rm "$file" 
done

【讨论】:

  • 如果您使用此方法,请务必将清单文件的名称添加到清单本身,以防您将其放在与您要删除文件的目录相同的目录中。如果将此代码放在脚本中,还要将该脚本的名称添加到清单中。
【解决方案3】:

只是为了好玩,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】:

    假设 MANIFEST 已经排序:

    find -type f -printf %P\\n | sort | comm -3 MANIFEST - | xargs rm
    

    【讨论】:

      【解决方案5】:

      想通了:

      ls -1 > ALLFILES
      comm -3 MANIFEST ALLFILES | xargs rm
      

      【讨论】:

      • 是的 comm -3 相当于我上面的解决方案。但要小心,因为 comm 期望已经排序的输入
      • 干杯,使用未排序的集合差异。
      • 如果您的文件名包含空格,请使用xargs -L 1
      猜你喜欢
      • 2010-09-06
      • 2022-10-17
      • 2021-11-20
      • 1970-01-01
      • 2019-01-03
      • 1970-01-01
      • 2015-01-02
      • 2022-12-14
      相关资源
      最近更新 更多