Batalkan kekacauan ekstraksi file tar

31

Saya baru saja membuka arsip yang menghasilkan kekacauan file ke direktori rapi saya. Sebagai contoh:

user@comp:~/tidy$ tar xvf myarchive.tar
file1
file2
dir1/
dir1/file1
dir1/subdir1/
dir1/subdir1/file1
dir2/
dir2/file1
...

Saya berharap bahwa file tar akan diatur dalam satu folder (mis., myarchive/ ), tapi ternyata tidak! Sekarang saya memiliki sekitar 190 file dan direktori yang secara digital muntah dalam apa yang merupakan direktori yang terorganisir. File-file yang belum diarsipkan ini perlu dibersihkan.

Apakah ada cara untuk "membatalkan" ini dan menghapus file dan direktori yang diambil dari arsip ini?


Terima kasih atas jawaban yang sangat baik di bawah ini. Singkatnya , inilah yang berfungsi dengan dua langkah (1) menghapus file, dan (2) menghapus struktur direktori kosong dalam urutan pengemasan terbalik (untuk menghapus direktori luar terlebih dahulu):

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

Dan lebih aman lagi, untuk melihat pratinjau perintah yang dijalankan dengan menambahkan echo setelah xargs.

Mike T
sumber
Saya kira Anda bisa membuat daftar file dalam arsip dan menghapusnya dari direktori saat ini, tetapi itu berpotensi merusak data (data yang ingin Anda simpan). Saya juga tidak tahu cara menulis skrip bash, jadi saya tidak bisa membantu di sana.
Bob
Untungnya, tidak ada yang ditimpa!
Mike T
Saya tidak mengejar rep dan saya takut saya akan terdengar jengkel tidak peduli bagaimana saya menempatkan ini, yang saya tidak (saya suka jawaban slhck juga dan saya +1: ed itu, dan jujur: ± 15 rep adalah tidak duniaku), tetapi akhirnya kamu menggunakan jawabanku yang disarankan dengan pipa dan xargs ( tac dari pada sort -r hanya kosmetik), tetapi Anda menerima jawaban dengan proses substitusi yang, seperti yang Anda jelaskan di komentar, tidak cocok untuk Anda? Juga, tolong beri xargs -d'\n' beralih di posting Anda jika Anda ingin merangkum untuk pengguna masa depan, sehingga mereka tidak akan digigit oleh spasi dalam nama file.
Daniel Andersson
@DanielAndersson, saya tidak pernah mengerti perlunya -d'\n' sampai sekarang, dan setelah dianalisis lebih lanjut, jawaban Anda sebenarnya mendekati apa yang saya gunakan.
Mike T
Benar-benar baik-baik saja dengan itu, suka solusi @ Daniel :) Perlunya -d'\n' terletak pada kenyataan bahwa jika Anda tidak memberi tahu xargs untuk membagi argumen pada baris baru (yang Anda beri makan) tetapi pada spasi, lalu file dengan nama folder1/some file akan dibaca sebagai folder1/some dan name.
slhck

Jawaban:

34
tar tf archive.tar

akan mencantumkan konten baris demi baris.

Ini dapat disalurkan ke xargs secara langsung, tetapi Waspadalah : lakukan penghapusan dengan sangat hati-hati. Kamu jangan ingin adil rm -r semua itu tar tf memberitahu Anda, karena itu mungkin termasuk direktori yang tidak kosong sebelum membongkar!

Anda bisa melakukannya

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

untuk pertama menghapus semua file yang ada di arsip, dan kemudian direktori yang dibiarkan kosong.

sort -r (saran glennjackman tac dari pada sort -r di komentar untuk jawaban yang diterima, yang juga berfungsi sejak saat itu tar Output cukup reguler) diperlukan untuk menghapus direktori terdalam terlebih dahulu; jika tidak demikian halnya dir1 berisi satu direktori kosong dir2 akan meninggalkan dir1 setelah rmdir lulus, karena itu tidak kosong sebelumnya dir2 telah dihapus.

Ini akan menghasilkan banyak

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

dan

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

Tutup ini dengan 2>/dev/null jika itu mengganggu Anda, tapi saya lebih suka menyimpan informasi sebanyak mungkin pada proses.

Dan jangan lakukan itu sampai Anda yakin bahwa Anda cocok dengan file yang tepat. Dan mungkin mencoba rm -i untuk mengkonfirmasi semuanya. Dan memiliki cadangan, makan sarapan, menyikat gigi, dll.

Daniel Andersson
sumber
Ya, akan lebih baik untuk lulus -d'\n' opsi untuk xargs.
Stéphane Gimenez
@ Slhck dan Stéphane: Ah, ya, saya akan memperbarui. Saya baru saja melakukan test case kecil, tetapi file tidak memiliki spasi.
Daniel Andersson
1
Perlu dicatat BSD itu xargs tidak punya -d, jadi Anda perlu varian GNU jika Anda adalah orang miskin seperti saya.
slhck
10

Daftar isi file tar seperti ini:

tar tzf myarchive.tar

Kemudian, hapus nama-nama file dengan mengulangi daftar itu:

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

Ini akan tetap adil daftar file yang akan dihapus. Menggantikan echo dengan rm jika Anda benar-benar yakin ini adalah yang ingin Anda hapus. Dan mungkin membuat cadangan untuk memastikan.

Dalam pass kedua, hapus direktori yang tersisa:

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

Ini mencegah direktori dengan dihapus jika sudah ada sebelumnya.


Trik bagus lainnya oleh @glennjackman, yang menjaga urutan file, mulai dari yang terdalam. Sekali lagi, hapus echo ketika selesai.

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

Ini kemudian bisa diikuti oleh yang normal rmdir membersihkan.

slhck
sumber
Cara aneh untuk menulis pipa.
Stéphane Gimenez
Nya tidak sebuah pipa. Nya substitusi proses dan saya lebih suka ini daripada perpipaan sederhana ketika digunakan dalam kombinasi dengan while untuk mengulang set rekaman. Baru terbiasa. @ sté
slhck
1
Maaf atas sedikit keterlambatan, saya perhatikan menggunakan itu rm -rf dapat menghapus file yang bukan dari arsip tetapi di dalam direktori yang memiliki nama yang sama dengan yang ada di arsip. Lebih baik berhati-hati di sini dan gunakan rmdir di umpan kedua.
Stéphane Gimenez
1
Sebenarnya lulus kedua dengan rmdir perlu dijalankan untuk setiap tingkat sarang direktori. Jadi itu akan bersih subdir1 pada pass pertama, tetapi pergi dir1 karena mencoba menghapus ini terlebih dahulu ketika tidak kosong pada saat itu. Perintah ini dapat dilakukan sekali jika daftar file dapat diurutkan mundur.
Mike T
3
Jika Anda ingin menghapus dalam urutan terbalik: tar tvf arch.tar | tac | xargs echo rm (hapus gema saat Anda yakin)
glenn jackman
2

Berikut adalah kemungkinan yang akan mengambil file yang diekstrak dan memindahkannya ke subdirektori, membersihkan folder utama Anda.

    #!/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";
    }

Simpan ini ke file fix-tar.pl dan kemudian jalankan seperti ini:

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

Ini akan mengkonfirmasi bahwa Anda tar daftar seperti milikku. Anda harus mendapatkan output seperti:

-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/

Jika itu terlihat bagus, jalankan lagi seperti ini:

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

Itu fixup.sh script akan menjadi perintah shell yang akan memindahkan file tingkat atas dan direktori ke folder "bersih" (dalam hal ini, folder bernama cleanup ). Lihat sekilas skrip ini untuk memastikan bahwa semuanya halal. Jika ya, Anda sekarang dapat membersihkan kekacauan Anda dengan:

$ sh fixup.sh

Saya lebih suka pembersihan seperti ini karena tidak merusak apa pun yang belum dihancurkan dengan ditimpa oleh inisial itu tar xv.

Catatan: jika output awal kering tidak terlihat benar, Anda harus bisa mengutak-atik angka dalam keduanya substr panggilan fungsi sampai terlihat layak. Itu $perms variabel hanya digunakan untuk dry run jadi hanya benar - benar $dirent Substring harus tepat.

Satu hal lagi: Anda mungkin perlu menggunakan tar pilihan --numeric-owner jika nama pengguna dan / atau nama grup dalam tar daftar membuat nama dimulai pada kolom yang tidak dapat diprediksi.

S2VpdGgA
sumber
1

Jenis arsip (antisosial) semacam itu disebut bom tar karena fungsinya. Setelah salah satu dari "meledak" pada Anda, solusi dalam jawaban lain jauh lebih baik daripada apa yang saya sarankan.

"Solusi" terbaik, bagaimanapun, adalah untuk mencegah masalah sejak awal.

Cara termudah (malas) untuk melakukannya adalah dengan selalu membongkar arsip tar ke direktori kosong. Jika itu termasuk direktori tingkat atas, maka Anda tinggal memindahkannya ke tujuan yang diinginkan. Jika tidak, maka cukup ganti nama direktori kerja Anda (yang kosong) dan pindahkan ke lokasi yang diinginkan.

Jika Anda hanya ingin memperbaikinya pertama kali, Anda dapat menjalankan tar -tvf archive-file.tar | kurang dan itu akan mencantumkan isi arsip sehingga Anda dapat melihat bagaimana itu disusun dan kemudian melakukan apa yang diperlukan untuk mengekstraknya ke lokasi yang diinginkan untuk memulai.

Opsi t juga berguna jika Anda ingin memeriksa isi arsip hanya untuk melihat apakah ada sesuatu yang Anda cari di dalamnya. Jika ya, Anda dapat, secara opsional, mengekstrak file yang Anda inginkan.

Joe
sumber