आंशिक रूप से ज़िपित विशाल सादे पाठ फ़ाइल को कैसे निकालना है?


19

मेरे पास 1.5 जीबी साइज वाली ज़िप फाइल है।

इसकी सामग्री एक हास्यास्पद बड़ी सादा-पाठ फ़ाइल (60 GB) है और मेरे पास वर्तमान में मेरी डिस्क पर पर्याप्त स्थान नहीं है जो इसे निकालने के लिए बचा है और न ही मैं यह सब निकालना चाहता हूं, भले ही मेरे पास था।

मेरे उपयोग के मामले के रूप में, यह पर्याप्त होगा यदि मैं सामग्री के कुछ हिस्सों का निरीक्षण कर सकता हूं।

इसलिए मैं फ़ाइल को एक स्ट्रीम के रूप में अनज़िप करना चाहता हूं और फ़ाइल की एक सीमा तक पहुंचना चाहता हूं (जैसे कि एक सामान्य मोबाइल फ़ाइल पर सिर और पूंछ के माध्यम से)।

या तो मेमोरी द्वारा (जैसे 32GB मार्क से शुरू अधिकतम 100kb निकालें) या लाइनों के द्वारा (मुझे प्लेन टेक्स्ट लाइनें 3700-3900 दें)।

वहाँ एक तरीका है कि प्राप्त करने के लिए है?


1
दुर्भाग्य से यह एक ज़िप के भीतर एक व्यक्तिगत फ़ाइल पर लेने के लिए संभव नहीं है। तो किसी भी
विवेचना

5
@plugwash जैसा कि मैं इस प्रश्न को समझता हूं, लक्ष्य ज़िप फ़ाइल (या यहां तक ​​कि विघटित फ़ाइल) के माध्यम से पढ़ने से बचने के लिए नहीं है, लेकिन बस पूरी तरह से विघटित फ़ाइल को मेमोरी या डिस्क पर संग्रहीत करने से बचने के लिए है । मूल रूप से, विघटित फ़ाइल को एक धारा के रूप में मानते हैं ।
श्रीवत्सआर

जवाबों:


28

ध्यान दें कि फ़ाइलें gzipनिकाल zipसकते हैं (कम से कम zipफ़ाइल में पहली प्रविष्टि )। इसलिए यदि उस संग्रह में केवल एक बहुत बड़ी फ़ाइल है, तो आप यह कर सकते हैं:

gunzip < file.zip | tail -n +3000 | head -n 20

उदाहरण के लिए 3000 वीं से शुरू होने वाली 20 लाइनों को निकालने के लिए।

या:

gunzip < file.zip | tail -c +3000 | head -c 20

बाइट्स के साथ एक ही बात के लिए (एक headकार्यान्वयन का समर्थन करता है -c)।

संग्रह में किसी भी अनियंत्रित सदस्य के लिए, यूनिक्स तरीके से:

bsdtar xOf file.zip file-to-extract | tail... | head...

के headअंतर्निहित ksh93(जैसे जब /opt/ast/binआगे है $PATH) के साथ, आप यह भी कर सकते हैं:

.... | head     -s 2999      -c 20
.... | head --skip=2999 --bytes=20

ध्यान दें कि किसी भी मामले में gzip/ bsdtar/ unzipहमेशा फ़ाइल को हटाने के लिए उस हिस्से की ओर जाता है, जिसे आप निकालना चाहते हैं। यह कैसे संपीड़न एल्गोरिथ्म काम करता है नीचे है।


यदि gzipइसे संभाल सकते हैं, तो अन्य "z जागरूक" उपयोगिताओं ( zcatऔर zless, आदि) भी काम करेंगे?
ivanivan

@ivanivan, सिस्टम पर जहां वे आधारित हैं gzip(आम तौर पर सच है zless, जरूरी नहीं कि zcatकुछ सिस्टम पर अभी भी .Zकेवल फाइलों को पढ़ना है), हाँ।
स्टीफन चेजलस

14

उदाहरण के लिए unzip -p और dd का उपयोग करते हुए एक समाधान, 1000 ब्लोक्स ऑफसेट के साथ 10kb निकालने के लिए:

$ unzip -p my.zip | dd ibs=1024 count=10 skip=1000 > /tmp/out

नोट: मैं वास्तव में बहुत बड़ा डेटा के साथ यह कोशिश नहीं की ...


किसी एकल संग्रह के अंदर एक से अधिक बार फ़ाइल के सामान्य मामले में unzip -l ARCHIVE, संग्रह सामग्री को सूचीबद्ध करने के लिए और unzip -p ARCHIVE PATHएकल वस्तु की सामग्री को निकालने के लिए उपयोग कर सकते हैं PATH
डेविड फ़ॉस्टर

3
आम तौर पर, ddगिनती या स्किप के साथ पाइप का उपयोग करना अविश्वसनीय होता है क्योंकि यह 1024 बाइट तक कई read()एस करेगा । तो यह केवल तभी ठीक से काम करने की गारंटी है यदि वह विखंडू में पाइप को लिखता है जिसका आकार 1024 से अधिक है।unzip
स्टीफन चेजालस

4

यदि आपका उस बड़ी ज़िप फ़ाइल के निर्माण पर नियंत्रण है, तो gzipऔर के संयोजन का उपयोग करने पर विचार क्यों नहीं किया जाता है zless?

यह आपको zlessपेजर के रूप में उपयोग करने की अनुमति देगा और निष्कर्षण से परेशान किए बिना फ़ाइल की सामग्री को देखेगा।

यदि आप संपीड़न प्रारूप को नहीं बदल सकते हैं तो यह स्पष्ट रूप से काम नहीं करेगा। यदि ऐसा है, तो मुझे लगता है zlessकि बल्कि सुविधाजनक है।


1
मैं नही। मैं बाहरी कंपनी द्वारा प्रदान की गई ज़िप्ड फ़ाइल डाउनलोड कर रहा हूं।
k0pernikus

3

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

unzip -p file.zip | sed -n 3700,3900p

7
sed -n 3700,3900pफ़ाइल के अंत तक पढ़ना जारी रखेगा। इससे sed '3700,$!d;3900q'बचने के लिए उपयोग करना बेहतर है, या यहां तक ​​कि आम तौर पर अधिक कुशल:tail -n +3700 | head -n 201
स्टीफन चेज़लस

3

मुझे आश्चर्य है कि अगर बात शुरू करने से लेकर फाइल करने तक की तुलना में अधिक कुशल कुछ भी करना संभव था। ऐसा प्रतीत होता है कि उत्तर नहीं है। हालाँकि, कुछ सीपीयू (स्काईलेक) zcat | tailपर सीपीयू पूरी घड़ी की गति तक नहीं चलता है। निचे देखो। एक कस्टम डिकोडर उस समस्या से बच सकता है और पाइप लेखन प्रणाली कॉल को बचा सकता है, और शायद ~ 10% तेज हो। (या यदि आप पावर-मैनेजमेंट सेटिंग्स को ट्वीक नहीं करते हैं तो स्काईलेक पर 60% तेजी से)।


किसी skipbytesफ़ंक्शन के साथ अनुकूलित ज़्लिब के साथ आप जो सबसे अच्छा कर सकते हैं वह वास्तव में विघटित ब्लॉक को फिर से संगठित करने के काम किए बिना एक संपीड़न ब्लॉक में प्रतीकों को पार्स करने के लिए होगा। यह एक ही बफर को अधिलेखित करने और फ़ाइल में आगे बढ़ने के लिए ज़ालिब के नियमित डिकोड फ़ंक्शन को कॉल करने की तुलना में काफी तेज (शायद कम से कम 2x) हो सकता है। लेकिन मुझे नहीं पता कि किसी ने ऐसा फंक्शन लिखा है या नहीं। (और मुझे लगता है कि यह वास्तव में तब तक काम नहीं करता है जब तक कि फाइल को एक विशेष ब्लॉक में डिकोडर को फिर से शुरू करने की अनुमति देने के लिए विशेष रूप से नहीं लिखा गया था)।

मैं उम्मीद कर रहा था कि डीकोड ब्लॉक के माध्यम से उन्हें डिकोड किए बिना छोड़ने का एक तरीका है, क्योंकि यह बहुत तेज़ होगा। हफ़मैन का पेड़ प्रत्येक ब्लॉक की शुरुआत में भेजा जाता है, इसलिए आप किसी भी ब्लॉक (मुझे लगता है) की शुरुआत से डिकोड कर सकते हैं। ओह, मुझे लगता है कि डिकोडर राज्य हफ़मैन पेड़ से अधिक है, यह डिकोड्ड डेटा के पिछले 32kiB भी है, और यह डिफ़ॉल्ट रूप से ब्लॉक सीमाओं पर रीसेट / भूल नहीं है। एक ही बाइट्स को बार-बार संदर्भित किया जा सकता है, इसलिए केवल एक बार एक विशाल संपीड़ित फ़ाइल में एक बार दिखाई दे सकता है। (उदाहरण के लिए एक लॉग फ़ाइल में, होस्टनाम सम्भवतः सम्पीडन शब्दकोश में "हॉट" रहता है, और इसका प्रत्येक उदाहरण पिछले वाले को संदर्भित करता है, पहले वाले को नहीं)।

zlibमैनुअल का कहना है कि आप उपयोग करने के लिए है Z_FULL_FLUSHजब बुला deflateअगर आप संकुचित धारा है कि बात करने के लिए seekable होना चाहता हूँ। यह "संपीड़न स्थिति को रीसेट करता है", इसलिए मुझे लगता है कि इसके बिना, पीछे के संदर्भ पिछले ब्लॉक (ओं) में जा सकते हैं। इसलिए, जब तक कि आपकी जिप फाइल कभी-कभी पूर्ण-फ्लश ब्लॉक्स के साथ नहीं लिखी जाती (जैसे हर 1G या कुछ का संपीड़न पर नगण्य प्रभाव होगा), मुझे लगता है कि आपको उस बिंदु तक डिकोड करने का काम अधिक करना होगा जो आप शुरू से चाहते हैं। विचारधारा। मुझे लगता है कि आप शायद किसी भी ब्लॉक की शुरुआत में शुरू नहीं कर सकते।


इस के बाकी हिस्सों को लिखा गया था जब मैं सोच रहा था कि यह संभव होगा कि आप पहले बाइट वाले ब्लॉक की शुरुआत का पता लगाएं, और वहां से डिकोड करें।

लेकिन दुर्भाग्य से, एक डिफ्लेट ब्लॉक की शुरुआत संपीड़ित ब्लॉकों के लिए यह संकेत नहीं देती है कि यह कितना लंबा है । असंगत डेटा को एक असम्पीडित ब्लॉक प्रकार के साथ कोडित किया जा सकता है जिसमें सामने की ओर बाइट्स में 16-बिट आकार होता है, लेकिन संकुचित ब्लॉक नहीं होते हैं: RFC 1951 प्रारूप का वर्णन बहुत आसानी से करता है । डायनेमिक हफ़मैन कोडिंग वाले ब्लॉक में ब्लॉक के सामने का पेड़ होता है (इसलिए डीकंप्रेसर को स्ट्रीम में तलाश नहीं करना पड़ता है), इसलिए कंप्रेसर को लिखने से पहले पूरे (संकुचित) ब्लॉक को मेमोरी में रखना होगा।

अधिकतम बैकवर्ड-रेफरेंस डिस्टेंस केवल 32kiB है, इसलिए कंप्रेसर को मेमोरी में बहुत अधिक असम्पीडित डेटा रखने की आवश्यकता नहीं है, लेकिन यह ब्लॉक आकार को सीमित नहीं करता है। ब्लॉक कई मेगाबाइट लंबे हो सकते हैं। (यह एक चुंबकीय ड्राइव पर भी डिस्क के लायक होने के लिए काफी बड़ा है, बनाम अनुक्रमिक मेमोरी में पढ़ा जाता है और रैम में केवल डेटा लंघन करता है, अगर यह संभव है कि इसके माध्यम से पार्स किए बिना वर्तमान ब्लॉक के अंत का पता लगाना)।

zlib जब तक संभव हो ब्लॉक बनाता है: मार्क एडलर के अनुसार , zlib केवल एक नया ब्लॉक शुरू करता है जब प्रतीक बफर भर जाता है, जो डिफ़ॉल्ट सेटिंग के साथ 16,383 प्रतीक (शाब्दिक या मैच) है


मैंने seq(जो कि बेहद बेमानी है और इस तरह शायद एक बड़ा परीक्षण नहीं है) का pv < /tmp/seq1G.gz | gzip -d | tail -c $((1024*1024*1000)) | wc -cआउटपुट ग़ज़ल में लिया, लेकिन उस पर स्केलेक i7-6700k पर केवल ~ 62 MiB / s का डेटा 3.9GHz पर चलता है, DDR2-2666 RAM के साथ। यह 246MiB / s विघटित डेटा है, जो memcpyकैश में फिट होने के लिए ब्लॉक आकार के लिए ~ 12 GiB / s की गति की तुलना में मोटा परिवर्तन है ।

(इसके बजाय energy_performance_preferenceडिफ़ॉल्ट पर सेट होने के साथ , स्काईलेक के आंतरिक सीपीयू गवर्नर केवल 2.7GHz पर चलने का निर्णय लेते हैं, ~ 43 MiB / संपीड़ित डेटा का उपयोग करते हैं। मैं इसका उपयोग करने के लिए उपयोग करता हूं । संभवतः ऐसी लगातार सिस्टम कॉल वास्तविक सीपीयू-बाउंड की तरह नहीं दिखती हैं। बिजली प्रबंधन इकाई के लिए काम करते हैं।)balance_powerbalance_performancesudo sh -c 'for i in /sys/devices/system/cpu/cpufreq/policy[0-9]*/energy_performance_preference;do echo balance_performance > "$i";done'

TL: DR: zcat | tail -cCPU एक तेज CPU पर भी बाध्य है, जब तक कि आपके पास बहुत धीमी डिस्क नहीं है। gzip ने उस पर चलने वाले CPU का 100% उपयोग किया (और प्रति घड़ी 1.81 निर्देश चलता था, उसी के अनुसार perf), और tailसीपीयू के 0.162 का उपयोग करता था (0.58 IPC)। प्रणाली अन्यथा बेकार थी।

मैं लिनक्स 4.14.11-1-ARCH का उपयोग कर रहा हूं, जिसमें केपीटीआई ने डिफ़ॉल्ट रूप से मेल्टडाउन के आसपास काम करने में सक्षम किया है , इसलिए वे सभी writeसिस्टम कॉल gzipअधिक महंगे हैं जो वे इस्तेमाल करते थे: /


बिल्ट-इन unzipया zcat(लेकिन फिर भी नियमित zlibडिकोड फ़ंक्शन का उपयोग करके ) चाहने से उन सभी पाइपों को लिखा जा सकेगा, और पूरी घड़ी की गति से चलने के लिए स्काइलेक सीपीयू मिलेंगे। (कुछ प्रकार के लोड के लिए यह डाउनलॉकिंग इंटेल स्काईलेक के लिए अद्वितीय है और बाद में, जिनके पास ओएस से सीपीयू आवृत्ति निर्णय लेना बंद है, क्योंकि उनके पास सीपीयू क्या कर रहा है, इसके बारे में अधिक डेटा है, और तेजी से ऊपर / नीचे रैंप कर सकता है।) सामान्य रूप से अच्छा है, लेकिन यहां स्काईलेक को अधिक रूढ़िवादी गवर्नर सेटिंग के साथ पूर्ण गति तक रैंप नहीं करना पड़ता है)।

कोई सिस्टम कॉल नहीं, बस एक बफर को फिर से लिखना जो L2 कैश में फिट बैठता है जब तक आप अपनी शुरुआती बाइट की स्थिति तक नहीं पहुंचते हैं, तो शायद कम से कम कुछ% अंतर होगा। शायद 10% भी, लेकिन मैं यहां केवल संख्या बना रहा हूं। मैंने यह zlibदेखने के लिए कोई विवरण नहीं दिया है कि कैश कैश फुटप्रिंट कितना बड़ा है, और टीपीबी फ्लश (और इस प्रकार यूओपी-कैश फ्लश) केपीटीआई सक्षम के साथ हर सिस्टम कॉल पर कितना नुकसान होता है।


कुछ सॉफ्टवेयर प्रोजेक्ट हैं जो gzip फाइल फॉर्मेट में एक सीक इंडेक्स जोड़ते हैं । इससे आपको मदद नहीं मिलती है अगर आप किसी को भी आपके लिए मांगने योग्य संपीड़ित फ़ाइलों को बनाने के लिए नहीं पा सकते हैं, लेकिन भविष्य के अन्य पाठकों को लाभ हो सकता है।

मुमकिन है इन परियोजनाओं के न तो एक डिकोड समारोह को पता है कि एक सूचकांक के बिना एक Deflate धारा के माध्यम से छोड़ करने के लिए कैसे, क्योंकि वे केवल काम करने के लिए डिज़ाइन कर रहे हैं जब एक सूचकांक है है उपलब्ध।

  • ज़िंगा: सीकेबल और स्प्लिटिबल गज़िप । बड़े ब्लॉक आकार की अनुमति देता है।
  • BGZF - अवरुद्ध, बड़ा और बेहतर GZIP! (छोटे अधिकतम ब्लॉक आकार = 64kiB संपीड़न अनुपात को थोड़ा नुकसान पहुंचाता है। एफआईटीटीए जैसे जैव सूचना विज्ञान डेटा के साथ उपयोग के लिए डिज़ाइन किया गया है, जो अक्सर कुछ अजगर पुस्तकालयों में पारदर्शी समर्थन के साथ असम्पीडित उपयोग किया जाता है।)

1

आप एक अजगर सत्र में ज़िप फ़ाइल को खोल सकते हैं, का उपयोग करके zf = zipfile.ZipFile(filename, 'r', allowZip64=True)और एक बार खोलने के बाद आप खोल सकते हैं, पढ़ने के लिए, ज़िप संग्रह के अंदर कोई भी फ़ाइल और लाइनों को पढ़ें, आदि, जैसे कि यह एक सामान्य फ़ाइल थी।

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