BASH: Как удалить все файлы, кроме названных в манифесте? - PullRequest
19 голосов
/ 06 мая 2010

У меня есть файл манифеста, который представляет собой список имен файлов, разделенных новой строкой. Как я могу удалить из папки все файлы, которые не названы в манифесте?

Я пытался построить команду 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

Оба игнорирует, отсортированы ли файлы / нет.

Ответы [ 5 ]

14 голосов
/ 07 мая 2010

Для каждого файла в текущем каталоге grep имя файла в файле MANIFEST и rm файл , если не совпадают.

for file in *
  do grep -q -F "$file" PATH_TO_YOUR_MANIFIST ||  rm "$file" 
done
13 голосов
/ 06 мая 2010

Использование шаблона «установить разницу» из 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 дважды, если в списке есть файлы, которых в действительности нет. Также обратите внимание, что выше поддерживаются файлы в подкаталогах

5 голосов
/ 06 мая 2010

разобрался:

ls -1 > ALLFILES
comm -3 MANIFEST ALLFILES | xargs rm
1 голос
/ 06 мая 2010

Просто для удовольствия, 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
0 голосов
/ 06 мая 2010

Предполагается, что MANIFEST уже отсортирован:

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