मैं टार फ़ाइल की सामग्री को कैसे फ़िल्टर कर सकता हूं, पाइप में एक और टार फ़ाइल का निर्माण कर रहा हूं?


13

बाहरी सिस्टम से एक सिंगल टार फाइल पर विचार करें, जिसमें विभिन्न विशेषताओं के साथ कुछ निर्देशिकाएं होती हैं, जिन्हें मैं अनुमतियों, mtimes, इत्यादि के साथ बनाए रखना चाहता हूं। मैं आसानी से एक नियमित उपयोगकर्ता (रूट नहीं) के रूप में इन फ़ाइलों का सबसेट कैसे ले सकता हूं?

कुछ इस तरह की तलाश में:

tar -f some.tar.gz --subset subdir/ | ssh remote@system tar xvz

यह भी आवश्यक है कि इस टार आर्काइव में मुख्य विशेषताओं (स्वामित्व, समूह, मोड, माइम) को बरकरार रखा जाए। विस्तारित फ़ाइल के रूप में टार फ़ाइल में अन्य विशेषताओं के बारे में क्या है ?

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

जवाबों:


14

bsdtar (libarchive के आधार पर) टार (और कुछ अन्य अभिलेखागार) को स्टड से स्टडआउट तक फ़िल्टर कर सकते हैं। उदाहरण के लिए, यह केवल एक पैटर्न से मेल खाते हुए फाइलनाम से होकर गुजरता है , और s/old/new/नामकरण कर सकता है । यह पहले से ही सबसे अधिक विकृतियों के लिए पैक किया गया है, उदाहरण के लिए bsdtarउबंटू में।

sudo apt-get install bsdtar   # or aptitude, if you have it.

# example from the man page:
bsdtar -c -f new.tar --include='*foo*' @old.tgz
#create new.tar containing only entries from old.tgz containing the string ‘foo’
bsdtar -czf - --include='*foo*' @-  # filter stdin to stdout, with gzip compression of output.

ध्यान दें कि इनपुट / आउटपुट के लिए संपीड़न प्रारूपों की एक विस्तृत पसंद है, इसलिए आपको स्वयं गनज़िप / एलज़ 4 के माध्यम से मैन्युअल रूप से पाइप करने की आवश्यकता नहीं है। आप वाक्यविन्यास के -साथ @tarfile, और / या -सामान्य की तरह स्टडआउट के लिए उपयोग कर सकते हैं ।


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

https://github.com/mafintosh/tar-stream


1
उत्कृष्ट, नहीं जानता था कि यह @original.tarदृष्टिकोण bsdtar के साथ संभव था। विस्तारित विशेषताओं और संपीड़न के साथ भी काम करने लगता है, </var/cache/pacman/pkg/libuv-1.7.0-1-x86_64.pkg.tar.xz bsdtar -czf - --include='usr/share/*' @- | tar tvz(और किसी कारण से एक खाली चयन शून्य बाइट्स की एक श्रृंखला का उत्पादन करता है, लेकिन यह मेरे लिए कोई बड़ी समस्या नहीं है)।
लेकेन्स्टाइन

1
मेरे परीक्षणों के अनुसार, @ old.tgz का उपयोग करके पुराने अभिलेखागार से आने वाली फ़ाइलों पर काम s/old/new/ नहीं करता है , यह केवल वास्तविक फाइलों पर काम करता है, सीधे फाइलसिस्टम से संग्रहित करता है। यह वास्तव में शर्म की बात है, क्योंकि यह मेरे लिए सबसे उपयोगी उपयोग मामला होगा।
बार्ट

4

सबसे आसान तरीका पूरे संग्रह की प्रतिलिपि बनाना होगा; मुझे लगता है कि आप ऐसा नहीं करना चाहते क्योंकि यह बहुत बड़ा है।

सामान्य कमांड लाइन टूल ( ) tar, paxएक संग्रह के सदस्यों को दूसरे संग्रह में कॉपी करने का समर्थन नहीं करते हैं।

यदि आपको स्वामित्व को संरक्षित करने की आवश्यकता नहीं है, तो मैं सुझाव देता हूं कि FUSE फाइल सिस्टम का उपयोग करें । आप एक पुरालेख को फाइलसिस्टम के रूप में माउंट करने के लिए आर्कमाउंट का उपयोग कर सकते हैं ; स्रोत संग्रह के लिए ऐसा करें, और माउंटेड फ़ाइल सिस्टम पर टार चलाएं।

archivemount some.tar.gz mnt
cd mnt
tar -cz subdir | ssh example.com tar -xz
fusermount -u mnt

वैकल्पिक रूप से, आप AVFS का उपयोग कर सकते हैं :

mountavfs
cd ~/.avfs$PWD/some.tar.gz\#
tar -cz subdir | ssh example.com tar -xz

वैकल्पिक रूप से, आप tarमूल संग्रह पर चल सकते हैं और SSHFS पर दूरस्थ मशीन को निकाल सकते हैं ।

sshfs example.com: mnt
cd mnt
tar -xf /path/to/some.tar.gz subdir
fusermount -u mnt

हालाँकि ये सभी तरीके बोझिल हैं यदि आपको स्वामित्व को संरक्षित करने की आवश्यकता है। वे सभी स्थानीय मशीन पर एक फ़ाइल को निकालने में शामिल हैं, इसलिए इस फ़ाइल के स्वामित्व का इरादा दूरस्थ स्वामित्व होना चाहिए । इसे रूट के रूप में चलाने की आवश्यकता होती है और यदि फाइल स्थानीय या मशीन और दूरस्थ होस्ट के बीच भिन्न नाम या आईडी वाले खातों के स्वामित्व में है, तो यह अपेक्षित परिणाम नहीं दे सकता है।

पायथन की tarfileलाइब्रेरी टार सदस्यों को हेरफेर करने के लिए एक काफी आसान तरीका प्रदान करती है, इसलिए आप उन्हें एक टार फाइल से दूसरे में फेरबदल कर सकते हैं। यह POSIX मानक प्रारूपों (ustar, pax) के साथ-साथ कुछ GNU एक्सटेंशन का समर्थन करता है। यहां एक अप्रमाणित पाइथन स्क्रिप्ट है जो अपने मानक इनपुट पर एक टार फाइल (संभवतः gzip या bzip2 के साथ संपीड़ित) पढ़ती है और अपने मानक आउटपुट पर bzip2 के साथ एक टार फाइल संपीड़ित लिखती है। यदि वे स्क्रिप्ट से पास किए गए तर्क से शुरू करते हैं, तो स्रोत से सदस्यों की प्रतिलिपि बनाई जाती है।

#!/usr/bin/env python2
import sys, tarfile
source = tarfile.open(fileobj=sys.stdin)
destination = tarfile.open(fileobj=sys.stdout, mode='w:bz2')
for info in source:
    if info.name.startswith(sys.argv[1]):
        destination.addfile(info)
destination.close()

के रूप में लागू किया जाना है

tar_filter <some.tar.gz subdir/ | ssh example.com tar -xj

1
bsdtar (libarchive पर आधारित) मक्खी पर टार अभिलेखागार फ़िल्टर कर सकते हैं, मेरा जवाब देखें।
पीटर कॉर्ड्स

कार्य एक फर्मवेयर छवि से डेटा निकालने के लिए था, इसलिए स्वामित्व / समूह सदस्यता वास्तव में महत्वपूर्ण है। अजगर दृष्टिकोण हालांकि काम कर सकता है।
लेकेनस्टाइन

0

एक वैकल्पिक विशेषाधिकार-कम दृष्टिकोण fakerootकार्यक्रम का उपयोग करने के लिए यह दिखावा है कि आपको स्वामित्व बदलने की अनुमति है। जबकि अन्य टार गुण खो जाते हैं, यह मोड, माइम और यूआईडी / जीआईडी ​​रखता है। ये कमांड एक अस्थायी निर्देशिका बनाते हैं, फाइलों का एक सबसेट निकालते हैं और अंत में एक नया संग्रह बनाते हैं:

mkdir tmp
<some.tar.gz \
fakeroot -- sh -c 'cd tmp && tar -xzf- subdir/ && tar -czf- subdir' |
   ssh remote@system tar -xzvf-
rm -rf tmp

0

GNU tarमें एक --deleteविकल्प है:

$ tar -c a b c | tar --delete a | tar -t
b
c

इस तरह, आप आउटपुट में शामिल नहीं करने के लिए निर्दिष्ट करके इनपुट टार का सबसेट प्राप्त कर सकते हैं ।

दुर्भाग्य से मुझे इसके --excludeसाथ काम करने का विकल्प नहीं मिला --delete, इसलिए ऐसा लगता है कि आपको -tहटाने के लिए पहले चीजों की एक स्पष्ट सूची ( ) प्राप्त करनी होगी और फिर इसे दूसरे मंगलाचरण में भेजना होगा tar

$ tar --delete --no-recursion `tar -t --exclude subdir <some.tar` <some.tar | ssh ...

या सूची को बाहरी फ़ाइल में संग्रहीत कर सकते हैं यदि यह बहुत लंबा या जटिल है:

$ tar -t --exclude subdir <some.tar >to_delete.lst
$ tar --delete --no-recursion -T to_delete.lst <some.tar | ssh ...

-1

जो मैं जानता हूं, tarकमांड इनपुट और आउटपुट दोनों के रूप में टार प्रारूप का उपयोग नहीं कर सकता है । आपको अपनी फ़ाइलों को स्थानीय रूप से किसी भी तरह निकालना होगा, और टारफाइल का उपयोग करने के लिए फिर से एक फ्लाई-ऑन-द-फ्लाई बनाना होगा, कुछ इस तरह से होगा ( -फ़ाइल के बजाय standart इनपुट / आउटपुट का उपयोग किया जाता है):

tar cf - subdir/ | ssh remote@system 'cd extractdir && tar xvf -'

ध्यान दें कि tarएक tarfile को सीधे दूसरे tarfile में निकालने में सक्षम होना एक दिलचस्प विचार है ...


जड़ के बिना यह सभी स्वामित्व / समूह जानकारी खो देगा, जिसे मैं स्पष्ट रूप से रखना चाहता हूं।
लेकेन्स्टाइन

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