เลิกทำการแยกไฟล์ tar ออก


34

ฉันไม่ได้เก็บถาวรที่สร้างความยุ่งเหยิงของไฟล์ลงในไดเรกทอรีที่เป็นระเบียบของฉัน ตัวอย่างเช่น:

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

ฉันคาดหวังว่าไฟล์ tar จะถูกจัดระเบียบในโฟลเดอร์เดียว (เช่นmyarchive/) แต่มันไม่ได้! ตอนนี้ฉันมีไฟล์และไดเร็กตอรี่ถึง 190 ไฟล์ที่มีการปิดบังแบบดิจิทัลในสิ่งที่เป็นไดเรกทอรีที่จัดระเบียบ ไฟล์ที่ไม่ได้จัดทำเหล่านี้จำเป็นต้องกำจัดให้หมด

มีวิธีใดในการ "เลิกทำ" สิ่งนี้และลบไฟล์และไดเรกทอรีที่ดึงมาจากไฟล์เก็บถาวรนี้หรือไม่?


ขอบคุณสำหรับคำตอบที่ดีเยี่ยมด้านล่าง โดยสรุปนี่คือสิ่งที่ใช้งานได้กับสองขั้นตอน (1) ลบไฟล์และ (2) ลบโครงสร้างไดเรกทอรีว่างในลำดับการบรรจุย้อนกลับ (เพื่อลบไดเรกทอรีด้านนอกก่อน):

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

และปลอดภัยมากขึ้นยังสามารถดูตัวอย่างแห้งทำงานของคำสั่งโดยท้ายหลังechoxargs


ฉันเดาว่าคุณสามารถแสดงรายการไฟล์ในไฟล์เก็บถาวรและลบออกจากไดเรกทอรีปัจจุบัน แต่นั่นอาจทำให้ข้อมูลเสียหายได้ (ข้อมูลที่คุณต้องการเก็บไว้) ฉันก็ไม่รู้เหมือนกันว่าจะเขียนสคริปต์ทุบตีดังนั้นฉันจึงไม่สามารถช่วยได้
Bob

โชคดีที่ไม่มีสิ่งใดถูกเขียนทับ!
Mike T

ฉันไม่ได้เป็นตัวแทนหลังจากและฉันกลัวว่าฉันจะฟังเสียงบ้าๆบอ ๆ ไม่ว่าฉันจะใส่สิ่งนี้ซึ่งฉันไม่ได้ (ฉันชอบคำตอบของ slhck เช่นกันและฉัน +1: ed มันและสุจริต: ± 15 ตัวแทนคือไม่ใช่โลกของฉัน) แต่คุณจบลงด้วยการใช้คำตอบที่แนะนำกับท่อและxargs( tacแทนที่จะsort -rเป็นแค่เครื่องสำอาง) แต่คุณยอมรับคำตอบด้วยการทดแทนกระบวนการที่ตามที่คุณอธิบายไว้ในความคิดเห็นที่ไม่เหมาะสมกับคุณ? นอกจากนี้โปรดให้xargs -d'\n'สวิตช์ในโพสต์ของคุณหากคุณต้องการสรุปสำหรับผู้ใช้ในอนาคตดังนั้นพวกเขาจะไม่ถูกเว้นวรรคในชื่อไฟล์
Daniel Andersson

@DanielAndersson ฉันไม่เคยเข้าใจถึงความจำเป็น-d'\n'จนถึงตอนนี้และจากการวิเคราะห์เพิ่มเติมคำตอบของคุณก็ใกล้เคียงกับสิ่งที่ฉันใช้
Mike T

โดยรวมแล้วก็ชอบโซลูชั่นของ @ Daniel :) ความจำเป็นของการ-d'\n'โกหกในความจริงที่ว่าถ้าคุณไม่บอกxargsให้แยกข้อโต้แย้งในบรรทัดใหม่ (ซึ่งเป็นสิ่งที่คุณกำลังให้อาหาร) แต่ในช่องว่างแล้วไฟล์ที่มี ชื่อfolder1/some fileจะได้รับการอ่านและfolder1/some name
slhck

คำตอบ:


36
tar tf archive.tar

จะแสดงรายการเนื้อหาทีละบรรทัด

สิ่งนี้สามารถถูกส่งไปยัง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 -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ยืนยันทุกอย่าง และมีข้อมูลสำรองกินอาหารเช้าแปรงฟัน ฯลฯ


ใช่มันจะดีกว่าที่จะผ่านตัวเลือกในการ-d'\n' xargs
Stéphane Gimenez

@slhck และStéphane: อ่าใช่ฉันจะอัปเดต ฉันเพิ่งทำกรณีทดสอบเล็กน้อย แต่ไฟล์ไม่มีที่ว่าง
Daniel Andersson

1
ควรสังเกตว่า BSD xargsไม่มี-dดังนั้นคุณต้องการตัวแปร GNU หากคุณเป็นคนจนอย่างฉัน
slhck

10

แสดงรายการเนื้อหาของไฟล์ 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ล้างปกติ


วิธีแปลก ๆ ในการเขียนไปป์
Stéphane Gimenez

มันไม่ใช่ท่อ มันเป็นการทดแทนกระบวนการและฉันชอบสิ่งนี้มากกว่าการวางท่ออย่างง่ายเมื่อใช้ร่วมกับwhileการวนรอบชุดของระเบียน เพิ่งได้ใช้มัน @ sté
slhck

1
ขออภัยในความล่าช้าเล็กน้อยฉันสังเกตเห็นว่าการใช้rm -rfสามารถลบไฟล์ที่ไม่ได้มาจากไฟล์เก็บถาวรได้ แต่ภายในไดเรกทอรีที่มีชื่อเดียวกับไฟล์จากไฟล์เก็บถาวร ดีกว่าระวังที่นี่และใช้rmdirในการผ่านครั้งที่สอง
Stéphane Gimenez

1
จริงๆแล้วการส่งผ่านครั้งที่สองที่มีrmdirความจำเป็นต้องเรียกใช้สำหรับการทำรังแต่ละระดับของไดเรกทอรี ดังนั้นมันจะล้างออกsubdir1ในบัตรผ่านแรก แต่ออกdir1เนื่องจากพยายามลบรายการนี้ก่อนเมื่อไม่มีเวลาว่าง คำสั่งนี้สามารถทำได้หนึ่งครั้งหากรายการไฟล์สามารถเรียงกลับกันได้
Mike T

3
หากคุณต้องการลบในลำดับย้อนกลับ: tar tvf arch.tar | tac | xargs echo rm(ลบเสียงก้องเมื่อคุณมั่นใจ)
glenn jackman

2

นี่คือความเป็นไปได้ที่จะนำไฟล์ที่แตกแล้วไปเก็บไว้ในไดเรกทอรีย่อยเพื่อล้างโฟลเดอร์หลักของคุณ

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

ถ้านั่นดูดีแล้วให้เรียกใช้อีกครั้งเช่นนี้:

$ 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ความต้องการที่จะเป็นสตริงย่อยที่เหมาะสม

อีกอย่างหนึ่ง: คุณอาจต้องใช้tarตัวเลือก--numeric-ownerหากชื่อผู้ใช้และ / หรือชื่อกลุ่มในtarรายการทำให้ชื่อเริ่มต้นในคอลัมน์ที่ไม่แน่นอน


1

การเก็บถาวร (ต่อต้านสังคม) ประเภทนั้นเรียกว่าระเบิดทาร์เนื่องจากสิ่งที่มันทำ เมื่อหนึ่งใน "ระเบิด" เหล่านี้กับคุณทางออกในคำตอบอื่น ๆ นั้นดีกว่าที่ฉันจะแนะนำ

อย่างไรก็ตาม "ทางออก" ที่ดีที่สุดคือการป้องกันปัญหาตั้งแต่แรก

วิธีที่ง่ายที่สุด (ขี้เกียจ) ในการทำเช่นนั้นคือการแตกไฟล์เก็บถาวร tar ลงในไดเรกทอรีว่างเสมอ หากมีไดเรกทอรีระดับบนสุดคุณก็ย้ายไปยังปลายทางที่ต้องการ ถ้าไม่เช่นนั้นให้เปลี่ยนชื่อไดเรกทอรีทำงานของคุณ (ไดเรกทอรีที่ว่างเปล่า) และย้ายไปยังตำแหน่งที่ต้องการ

หากคุณต้องการทำให้ถูกต้องในครั้งแรกคุณสามารถเรียกใช้ tar -tvf archive-file.tar | น้อยลงและจะแสดงรายการเนื้อหาของไฟล์เก็บถาวรเพื่อให้คุณสามารถดูว่ามีโครงสร้างอย่างไรแล้วทำสิ่งที่จำเป็นเพื่อแยกไฟล์ออกไปยังตำแหน่งที่ต้องการเพื่อเริ่มต้นด้วย

ตัวเลือก t มีประโยชน์ถ้าคุณต้องการตรวจสอบเนื้อหาของไฟล์เก็บถาวรเพื่อดูว่ามีบางสิ่งที่คุณต้องการหรือไม่ ถ้าเป็นเช่นนั้นคุณสามารถเลือกที่จะแยกไฟล์ที่คุณต้องการ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.