टार फ़ाइल निष्कर्षण गंदगी पूर्ववत करें


34

मैं सिर्फ एक संग्रह को अनसुना कर दूंगा जिसने मेरी सुव्यवस्थित निर्देशिका में फ़ाइलों की गड़बड़ी पैदा की। उदाहरण के लिए:

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

मैं उम्मीद कर रहा था कि टार फ़ाइल एक एकल फ़ोल्डर (यानी myarchive/) में आयोजित की गई होगी , लेकिन यह नहीं थी! अब मेरे पास कुछ 190 फाइलें और निर्देशिकाएं हैं जो एक संगठित निर्देशिका थी जो डिजिटल रूप से बारफेड है। इन अनट्रेड फ़ाइलों को साफ़ करने की आवश्यकता है।

क्या इसे "पूर्ववत" करने और इस संग्रह से निकाले गए फ़ाइलों और निर्देशिकाओं को हटाने का कोई तरीका है?


नीचे दिए गए उत्कृष्ट उत्तरों के लिए धन्यवाद। सारांश में , यहाँ दो चरणों के साथ काम करता है (1) फ़ाइलें हटाएँ, और (2) खाली निर्देशिका संरचना को रिवर्स पैकिंग ऑर्डर में हटाएं (बाहरी निर्देशिकाओं को पहले हटाने के लिए):

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

और अभी तक सुरक्षित, के echoबाद से जोड़कर आदेशों की एक सूखी चलाने का पूर्वावलोकन करने के लिए xargs


मुझे लगता है कि आप संग्रह में फ़ाइलों को सूचीबद्ध कर सकते हैं और उन्हें वर्तमान निर्देशिका से हटा सकते हैं, लेकिन यह संभावित डेटा विनाशकारी (आप जिस डेटा को रखना चाहते हैं) महसूस करता है। मुझे यह भी पता नहीं है कि बैश स्क्रिप्ट कैसे लिखी जाती है, इसलिए मैं वहां मदद नहीं कर सकता।
बॉब

सौभाग्य से, कुछ भी नहीं लिखा गया था!
माइक टी

मैं रेप के बाद नहीं हूं और मुझे डर है कि मैं क्रैंक को आवाज दूंगा चाहे मैं इसे कैसे भी रखूं, लेकिन मैं ऐसा नहीं हूं (मुझे स्लहॉक का जवाब पसंद आया और मैं इसे एड करता हूं और ईमानदारी से: and 15 प्रतिनिधि है मेरी दुनिया नहीं ), लेकिन आप पाइपों के साथ मेरे सुझाए गए उत्तर का उपयोग करके समाप्त हो गए हैं xargs( और tacइसके बजाय sort -rसिर्फ सौंदर्य प्रसाधन हैं), लेकिन आप प्रक्रिया प्रतिस्थापन के साथ उत्तर स्वीकार करते हैं, जैसा कि आपने टिप्पणियों में समझाया था, क्या आप फिट नहीं हुए? इसके अलावा, xargs -d'\n'यदि आप भविष्य के उपयोगकर्ताओं के लिए संक्षेप में प्रस्तुत करना चाहते हैं , तो कृपया अपनी पोस्ट में स्विच दें , ताकि वे फ़ाइल नामों में रिक्त स्थान से काट न लें।
डैनियल एंडरसन

@ डैनियलएंडरसन, मैंने -d'\n'अब तक की आवश्यकता को कभी नहीं समझा , और आगे के विश्लेषण पर आपका जवाब वास्तव में मेरे द्वारा उपयोग किए जाने के करीब है।
माइक टी

उस के साथ पूरी तरह से ठीक है, @ डैनियल समाधान पसंद आया :) इस -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(ग्लेनजैकमैन ने स्वीकृत उत्तर के लिए टिप्पणियों के 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
स्टीफन जिमेनेज़

@ शेल्के और स्टीफन: आह, हां, मैं अपडेट करूंगा। मैंने सिर्फ एक छोटा सा परीक्षण किया, लेकिन फाइलों में कोई जगह नहीं थी।
डैनियल एंडरसन

1
ध्यान दिया जाना चाहिए कि बीएसडी के xargsपास नहीं है -d, इसलिए आपको जीएनयू संस्करण की आवश्यकता है यदि आप मेरी तरह एक गरीब आत्मा हैं।
slhck

10

टार फ़ाइल की सामग्री को इस तरह सूचीबद्ध करें:

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सफाई की जा सकती है ।


पाइप लिखने का अजीब तरीका।
स्टीफन जिमेनेज़

यह एक पाइप नहीं है। यह प्रक्रिया प्रतिस्थापन है और मैं इसे सरल पाइपिंग पर पसंद करता हूं जब whileरिकॉर्ड के एक सेट पर लूप के साथ संयोजन में उपयोग किया जाता है । बस आदत हो गई। @ Ste
slhck

1
थोड़ी देरी के लिए क्षमा करें, मैंने देखा कि उन rm -rfफ़ाइलों को हटा दिया जा सकता है जो संग्रह से नहीं थीं, लेकिन एक निर्देशिका के अंदर, जिसका नाम संग्रह से एक जैसा है। यहां बेहतर सावधानी बरतें और rmdirएक दूसरे पास में उपयोग करें ।
स्टीफन जिमेनेज़

1
वास्तव rmdirमें निर्देशिका के घोंसले के शिकार के लिए प्रत्येक स्तर के लिए दूसरा पास होना चाहिए। तो यह subdir1पहली पास पर साफ हो जाएगा , लेकिन dir1जब यह खाली नहीं था, तो इसे हटा दें । यह कमांड एक बार किया जा सकता है यदि फ़ाइल सूची को उलटा किया जा सकता है।
माइक टी

3
यदि आप रिवर्स ऑर्डर में हटाना चाहते हैं: tar tvf arch.tar | tac | xargs echo rm(ईको को हटा दें जब आप आश्वस्त हों)
ग्लेन जैकमैन

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


1

इस तरह के (असामाजिक) संग्रह को टार बम कहा जाता है क्योंकि यह क्या करता है। एक बार जब आप में से कोई एक "विस्फोट" करता है, तो अन्य उत्तरों में समाधान मेरे द्वारा सुझाए गए तरीकों से बेहतर होते हैं।

हालांकि, सबसे अच्छा "समाधान" पहली जगह में समस्या को रोकने के लिए है।

सबसे आसान (laziest) तरीका यह है कि हमेशा एक खाली डायरेक्टरी में टार आर्काइव को अनपैक करें। यदि इसमें एक शीर्ष स्तर की निर्देशिका शामिल है, तो आप इसे वांछित गंतव्य पर ले जाते हैं। यदि नहीं, तो बस अपनी कार्यशील निर्देशिका (जो खाली थी) का नाम बदलें और उसे इच्छित स्थान पर ले जाएँ।

यदि आप इसे पहली बार ठीक करना चाहते हैं, तो आप tar -tvf संग्रह-file.tar चला सकते हैं | कम है और यह संग्रह की सामग्री को सूचीबद्ध करेगा ताकि आप देख सकें कि यह कैसे संरचित है और फिर शुरू करने के लिए वांछित स्थान पर इसे निकालने के लिए क्या करना आवश्यक है।

यदि आप किसी संग्रह की सामग्री का निरीक्षण करना चाहते हैं, तो यह देखने के लिए टी विकल्प भी काम में आता है कि क्या आपके पास कुछ ऐसा है जिसे आप खोज रहे हैं। यदि ऐसा होता है, तो आप वैकल्पिक रूप से, केवल वह फ़ाइल निकाल सकते हैं जिसे आप चाहते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.