Отменить удаление файла tar-файла

Я просто распаковал архив, создавший беспорядок файлов в мой аккуратный каталог. Например:

[email protected]:~/tidy$ tar xvf myarchive.tar file1 file2 dir1/ dir1/file1 dir1/subdir1/ dir1/subdir1/file1 dir2/ dir2/file1 ... 

Я ожидал, что tar-файл будет организован в одной папке (т.е. myarchive/ ), но это не так! Теперь у меня есть 190 файлов и каталогов, которые имеют цифровое ограничение в том, что было организованным каталогом. Эти файлы untar'd необходимо очистить.

Есть ли способ «отменить» это и удалить файлы и каталоги, извлеченные из этого архива?


Спасибо за отличные ответы ниже. Вкратце , вот что работает с двумя шагами (1) удаляет файлы и (2) удаляет пустую структуру каталога в обратном порядке упаковки (сначала удалять внешние каталоги):

 tar tf myarchive.tar | xargs -d'\n' rm tar tf myarchive.tar | tac | xargs -d'\n' rmdir 

И еще безопаснее просмотреть предварительный просмотр команд, добавив echo после xargs .

 tar tf archive.tar 

Перечислит содержимое по строкам.

Это можно напрямую xargs в xargs , но будьте осторожны : сделайте удаление очень осторожно. Вы не хотите просто rm -r все, что говорит tar tf , поскольку оно может включать каталоги, которые не были пустыми перед распаковкой!

Вы могли бы сделать

 tar tf archive.tar | xargs -d'\n' rm -v tar tf archive.tar | sort -r | xargs -d'\n' rmdir -v 

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

Sort sort -r (glennjackman предложил tac вместо sort -r в комментариях к принятому ответу, который также работает, поскольку вывод tar достаточно регулярный) необходимо сначала удалить самые глубокие каталоги; В противном случае случай, когда dir1 содержит один пустой каталог dir2 выйдет из dir1 после прохода rmdir , так как он не был пуст до удаления dir2 .

Это создаст много

 rm: cannot remove `dir/': Is a directory 

а также

 rmdir: failed to remove `dir/': Directory not empty rmdir: failed to remove `file': Not a directory 

Закройте это с помощью 2>/dev/null если это вас раздражает, но я предпочел бы хранить как можно больше информации о процессе.

И не делайте этого, пока не убедитесь, что вы соответствуете правильным файлам. И, возможно, попробуйте rm -i чтобы все подтвердить. И иметь резервные копии, есть свой завтрак, чистить зубы и т. Д.

Перечислите содержимое файла tar следующим образом:

 tar tzf myarchive.tar 

Затем удалите эти имена файлов, итерации по этому списку:

 while IFS= read -r file; do echo "$file"; done < <(tar tzf myarchive.tar.gz) 

Это все равно будет просто список файлов, которые будут удалены. Замените echo на rm если вы действительно уверены, что это те, которые вы хотите удалить. И, возможно, сделайте резервную копию, чтобы быть уверенным.

На втором проходе удалите оставшиеся каталоги:

 while IFS= read -r file; do rmdir "$file"; done < <(tar tzf myarchive.tar.gz) 

Это предотвращает удаление каталогов, если они уже существовали раньше.


Еще один приятный трюк от @glennjackman, который сохраняет порядок файлов, начиная с самых глубоких. Снова удалите echo когда закончите.

 tar tvf myarchive.tar | tac | xargs -d'\n' echo rm 

Затем после этого можно было бы выполнить обычную очистку rmdir .

Вот возможность, которая возьмет извлеченные файлы и переместит их в подкаталог, очистив вашу основную папку.

  #!/usr/bin/perl -w use strict; use Getopt::Long; my $clean_folder = "clean"; my $DRY_RUN; die "Usage: $0 [--dry] [--clean=dir-name]\n" if ( !GetOptions("dry!" => \$DRY_RUN, "clean=s" => \$clean_folder)); # Protect the 'clean_folder' string from shell substitution $clean_folder =~ s/'/'\\''/g; # Process the "tar tv" listing and output a shell script. print "#!/bin/sh\n" if ( !$DRY_RUN ); while (<>) { chomp; # Strip out permissions string and the directory entry from the 'tar' list my $perms = substr($_, 0, 10); my $dirent = substr($_, 48); # Drop entries that are in subdirectories next if ( $dirent =~ m:/.: ); # If we're in "dry run" mode, just list the permissions and the directory # entries. # if ( $DRY_RUN ) { print "$perms|$dirent\n"; next; } # Emit the shell code to clean up the folder $dirent =~ s/'/'\\''/g; print "mv -i '$dirent' '$clean_folder'/.\n"; } 

Сохраните это в файле fix-tar.pl а затем выполните его следующим образом:

 $ tar tvf myarchive.tar | perl fix-tar.pl --dry 

Это подтвердит, что ваш список tar похож на мой. Вы должны получить вывод, например:

 -rw-rw-r--|batch -rw-rw-r--|book-report.png -rwx------|CaseReports.png -rw-rw-r--|caseTree.png -rw-rw-r--|tree.png drwxrwxr-x|sample/ использованием -rw-rw-r--|batch -rw-rw-r--|book-report.png -rwx------|CaseReports.png -rw-rw-r--|caseTree.png -rw-rw-r--|tree.png drwxrwxr-x|sample/ 

Если это выглядит хорошо, запустите его снова следующим образом:

 $ mkdir cleanup $ tar tvf myarchive.tar | perl fix-tar.pl --clean=cleanup > fixup.sh 

fixup.sh будет командами оболочки, которые будут перемещать файлы и каталоги верхнего уровня в «чистую» папку (в данном случае – в папку с именем cleanup ). Посмотрите на этот сценарий, чтобы убедиться, что он все кошерный. Если это так, вы можете очистить свой беспорядок:

 $ sh fixup.sh 

Я предпочитаю эту очистку, потому что она не уничтожает ничего, что еще не уничтожено, будучи перезаписано этим начальным tar xv .

Примечание: если этот начальный выход с сухим проходом не выглядит правильным, вы должны быть в состоянии возиться с числами в двух вызовах функций substr пока они не выглядят надлежащим образом. Переменная $perms используется только для сухого прогона, поэтому действительно $dirent подстрока $dirent .

Еще одна вещь: вам может понадобиться использовать параметр tar --numeric-owner если имена пользователей и / или имена групп в листинге tar заставляют имена запускаться в непредсказуемом столбце.

Такой (антисоциальный) архив называется бочкой из-за того, что она делает. Когда один из этих «взрывается» на вас, решения в других ответах лучше, чем я бы предложил.

Лучшее «решение», однако, состоит в том, чтобы предотвратить проблему в первую очередь.

Самый простой (ленивый) способ сделать это – всегда распаковать tar-архив в пустой каталог. Если он содержит каталог верхнего уровня, то вы просто переместите его в нужное место назначения. Если нет, просто переименуйте свой рабочий каталог (тот, который был пуст) и переместите его в нужное место.

Если вы просто хотите, чтобы все было правильно в первый раз, вы можете запустить tar -tvf archive-file.tar | Меньше, и он будет перечислять содержимое архива, чтобы вы могли видеть, как он структурирован, а затем делать то, что необходимо, чтобы извлечь его в нужное место для начала.

Опция t также полезна, если вы хотите проверить содержимое архива только для того, чтобы увидеть, есть ли у него что-то, что вы ищете. Если это так, вы можете, при желании, просто извлечь нужные вам файлы.

Давайте будем гением компьютера.