अलग-अलग निर्देशिकाओं में कई फ़ाइलों को गज़िप करें और नई निर्देशिका में कॉपी करें


4

मैं कई फाइलों के साथ काम कर रहा हूं जो अलग-अलग निर्देशिकाओं में स्थित हैं जिन्हें मुझे अलग-अलग .gz फ़ाइलों में संपीड़ित करने की आवश्यकता है। मुझे केवल मूल को छोड़ते हुए संपीड़ित फ़ाइलों को एकल निर्देशिका में ले जाने की आवश्यकता है।

क्या gzip कमांड और एक फ़ाइल का उपयोग करने का एक तरीका है जिसमें उन फ़ाइलों के सभी फ़ाइल पथों की सूची है, जिन्हें मैं संक्षिप्त करना चाहता हूं?

माफी अगर यह थोड़ा लंबा है ... मैं लिनक्स के लिए काफी नया हूं और इसे बेहतर बनाने के अधिक कुशल तरीके के बारे में नहीं सोच सकता।

जवाबों:


4

फाइलों की सूची मानकर फाइल फाइलिस्ट (प्रति पंक्ति एक फ़ाइल पथ) में संग्रहित किया जाता है और आप संपीड़ित फ़ाइलों को zipdir में संग्रहीत करना चाहते हैं , यह बैश स्क्रिप्ट वांछित परिणाम प्राप्त करेगी:

#!/bin/bash

while IFS= read file; do
    gzip -c "$file" > "zipdir/$(basename "$file").gz"
done < filelist

बैश / डैश में, आप उपर्युक्त को वन-लाइनर में भी बदल सकते हैं:

while IFS= read file; do gzip -c "$file" > "zipdir/$(basename "$file").gz"; done < filelist

अन्य गोले में (उदाहरण के लिए, tsh या zsh)

bash -c 'while IFS= read file; do gzip -c "$file" > "zipdir/$(basename "$file").gz"; done < filelist'

नौकरी करेंगे।

यदि बैश मौजूद नहीं है, तो इसे डैश के साथ प्रतिस्थापित किया जा सकता है।

यह काम किस प्रकार करता है

  • ... < filelistकी सामग्री को पुनर्निर्देश filelist के लिए ...

  • while IFS= read file; do ... doneफाइलिस्ट में लाइनों के माध्यम से जाता है, चर फ़ाइल में वर्तमान में संसाधित लाइन की सामग्री को संग्रहीत करता है और निष्पादित करता है ...

    IFS=आंतरिक फ़ाइल विभाजक को संशोधित करता है। यह कई, प्रमुख और अनुगामी रिक्त स्थान को ठीक से संभालने के लिए आवश्यक है।

  • gzip -c "$file" > "zipdir/$(basename "$file").gz"वर्तमान में संसाधित फ़ाइल को संपीड़ित करता है और आउटपुट को उसी नाम के साथ फ़ाइल में संग्रहीत करता है और निर्देशिका zipdir में .gz एक्सटेंशन देता है ।

    यहाँ basename "$file"फ़ाइल के पथ से नंगे फ़ाइलनाम को निकालता है।


अपनी त्वरित प्रतिक्रिया के लिए धन्यवाद! ऐसा लगता है कि यह सही रास्ते पर है जहाँ मैं जाना चाहता हूँ। हालाँकि, मैं जिस व्यक्ति के लिए काम करता हूं वह tcsh (मुझे लगता है कि उन्होंने जो सीखा है) को पसंद करता है और इसलिए मैं जिस बॉक्स पर काम करता हूं वह उस शेल में चलता है। क्या इसे लिखने का कोई तरीका है इसलिए यह tcsh में काम करेगा?
डेविड

उपरोक्त को tcsh में पोर्ट करना बहुत कठिन नहीं होना चाहिए, लेकिन मैं ऐसा करने के लिए लगभग पर्याप्त tsh नहीं हूं। जब तक बैश स्थापित होता है, तब तक यह एक स्क्रिप्ट के लिए उपरोक्त को बचाने और बैश शेबंग को जोड़ने या इसके साथ आह्वान करने के लिए पर्याप्त है bash -c
डेनिस

ठीक है, बहुत बढ़िया। मैं कोशिश करूँगा। आपकी मदद के लिए बहुत धन्यवाद!!
डेविड

बस यह कोशिश की और सब कुछ पूरी तरह से काम करता है! हालाँकि, मेरा एक और सवाल है। जब मेरी उड़ने की समाप्ति समाप्त हो जाती है (सभी अन्य फ़ाइलों को सफलतापूर्वक कॉपी / संपीड़ित करने के बाद), स्क्रिप्ट आगे चलकर नीचे की ओर पढ़ने की कोशिश करती रहती है, लेकिन चूंकि कोई फ़ाइल पथ नहीं बचा है इसलिए यह केवल एक खाली .gz फ़ाइल बनाता है और मुझे देता है। "ऐसी कोई फ़ाइल या निर्देशिका नहीं" की त्रुटि। क्या कोई ऐसी चीज है जिसे मैं अपनी फ्लेस्ट के अंत में जोड़ सकता हूं ताकि वह स्क्रिप्ट को बता सके कि यह अंत तक पहुंच गया है?
डेविड

पटकथा व्हाट्सएप-संवेदी है। यदि अंत में एक पंक्ति है जिस पर एक सिंगल स्पेस है, तो यह एक `.gz` फ़ाइल (नोट लीडिंग स्पेस) बनाएगा। एक खाली लाइन (जिसमें स्पेस भी नहीं है) के परिणामस्वरूप समान त्रुटि होगी, लेकिन कोई खाली फ़ाइल नहीं।
डेनिस

0

मुझे नहीं लगता कि gzipकिसी फ़ाइल से पठन पथ का समर्थन करता है। वर्कअराउंड या तो सभी टारगेट फाइलों को एक आर्काइव (टार) में डालना होगा या इसे कई बार निष्पादित करना होगा।

यदि लक्ष्य निर्देशिका क्षमता या स्थानांतरण गति के संबंध में सीमित नहीं है, तो इस उत्तर में उल्लिखित लक्ष्य फ़ोल्डर में उन्हें संपीड़ित करने से पहले फ़ाइलों को स्थानांतरित करने के लिए एक संभावित समाधान होगा ।

अन्यथा, आप एक बार में एक ही फ़ाइल नाम पढ़ते हैं, जैसे ही आप जाते हैं, उनके फ़ोल्डरों को संकुचित करना और बनाना।

फ़ोल्डर संरचना बनाएँ

TARGET=~/tmp/out

while read line; do 
    dirname "$line" ; 
done < list.txt | sort -u |
xargs -I%  echo mkdir -p "$TARGET/%"

  ## out: ##
  mkdir /home/jaroslav/tmp/out/code/bash 
  mkdir /home/jaroslav/tmp/out/recipes
  mkdir /home/jaroslav/tmp/out/samba
  mkdir /home/jaroslav/tmp/out/wikipedia

फ़ाइलों की प्रतिलिपि बनाएँ

while read line; do
   gzip -c "$SOURCE/$line" > "$TARGET/$line.gz"
done < list.txt

आदेश

  • dirname: एक filepath के अंतिम भाग को हटा दें, निर्देशिका को छोड़कर
  • [arg] <फ़ाइल पढ़ें: फ़ाइल से एक समय में एक पंक्ति पढ़ें और शेल चर arg में संग्रहीत करें
  • सॉर्ट -u: डुप्लिकेट प्रविष्टियों को हटा दें ( uनिक को छोड़ दें )
  • xargs -I%: पाइप से हर तत्व (dir नाम) के लिए एक बार कमांड (इको ....) निष्पादित करें!)
  • gzip -c in> out: stdout (-c) में संपीड़ित करें और लिखें। > एक फ़ाइल के लिए स्टड पुनर्निर्देशित करता है जिसका नाम है।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.