फाइल की शुरुआत से बाइट्स हटाने का सबसे अच्छा तरीका?


61

आज मुझे 800MB मिश्रित पाठ / बाइनरी फ़ाइल से पहले 1131 बाइट्स को निकालना था, एक फ़िल्टर किए गए तोड़फोड़ डंप मैं एक नए रिपॉजिटरी के लिए हैकिंग कर रहा हूं। ऐसा करने का सबसे अच्छा तरीका क्या है?

शुरुआत करने के लिए मैंने कोशिश की

dd bs=1 skip=1131 if=filtered.dump of=trimmed.dump

लेकिन स्किप करने के बाद यह एक बार में बाइट फ़ाइल के शेष को कॉपी करता है, यानी बहुत धीरे-धीरे। अंत में मैंने काम किया मुझे 512 के तीन ब्लॉक तक इसे गोल करने के लिए 405 बाइट की आवश्यकता थी जिसे मैं छोड़ सकता था

dd if=/dev/zero of=405zeros bs=1 count=405
cat 405zeros filtered.dump | dd bs=512 skip=3 of=trimmed.dump

जो काफी जल्दी पूरा हो गया है लेकिन एक सरल / बेहतर तरीका रहा होगा? क्या कोई अन्य उपकरण है जिसके बारे में मैं भूल गया हूं? धन्यवाद!


ddनौकरी के लिए सही उपकरण है - ऐसा लगता है कि आप अपनी समस्या का एक अच्छा, सुरुचिपूर्ण समाधान लेकर आए हैं।
जस्टिन एथियर

जवाबों:


62

आप bs स्विच कर सकते हैं और विकल्प छोड़ सकते हैं:

dd bs=1131 skip=1 if=filtered.dump of=trimmed.dump

इस तरह ऑपरेशन एक बड़े ब्लॉक से लाभ उठा सकता है।

अन्यथा, आप पूंछ के साथ प्रयास कर सकते हैं (हालांकि बाइनरी फ़ाइलों के साथ इसका उपयोग करना सुरक्षित नहीं है):

tail -c +1132 filtered.dump >trimmed.dump

अंत में, आप कुछ लिखने के लिए 3 dd उदाहरणों का उपयोग कर सकते हैं:

dd if=filtered.dump bs=512k | { dd bs=1131 count=1 of=/dev/null; dd bs=512k of=trimmed.dump; }

जहां पहला dd अपने मानक आउटपुट को फ़िल्टर करता है। दूसरा व्यक्ति सिर्फ 1131 बाइट्स पढ़ता है और उन्हें फेंक देता है; फिर, अंतिम अपने मानक इनपुट से फ़िल्टर किए गए बाइट्स के शेष बाइट्स को पढ़ता है और उन्हें trimmed.dump पर लिखता है।


6
धन्यवाद! मुझे नहीं पता था कि पाइप किए गए इनपुट को इस तरह से दूसरी प्रक्रिया में ले जाया गया है - यह बहुत साफ है। मुझे विश्वास नहीं हो रहा है कि मैं इसके बारे में नहीं सोचता bs=1131 skip=1: - /
Rup

2
शेल उपयोगिताओं के अधिकांश आधुनिक कार्यान्वयन बाइनरी फ़ाइलों के साथ सही तरीके से काम करते हैं (अर्थात उन्हें अशक्त पात्रों से कोई परेशानी नहीं है और फ़ाइल के अंत में एक अतिरिक्त नई रेखा नहीं डालेंगे)। निश्चित रूप से जीएनयू और * बीएसडी कार्यान्वयन सुरक्षित हैं।
गाइल्स

17

निश्चित नहीं है कि कब skip_bytesजोड़ा गया था, लेकिन आपके पास पहले 11 बाइट्स को छोड़ने के लिए:

# echo {123456789}-abcdefgh- | 
                              dd bs=4096 skip=11 iflag=skip_bytes
-abcdefgh-
0+1 records in
0+1 records out
11 bytes (11 B) copied, 6.963e-05 s, 158 kB/s

जहां iflag=skip_bytesdd को skipब्लॉक के बजाय बाइट्स के रूप में विकल्प के लिए मूल्य की व्याख्या करने के लिए कहता है , जिससे यह सीधा हो जाता है।


निश्चित रूप से बड़ी फ़ाइलों के लिए गति का लाभ और डेटा की थोड़ी मात्रा को हटाया जाना चाहिए।
sstn

यह सबसे अच्छा उत्तर है, क्योंकि यह हर ब्लॉक आकार के लिए काम करता है जैसेiflag=skip_bytes skip=1234 bs=1M
phiresky

15

आप एक उप-शेल और दो ddकॉल का उपयोग कर सकते हैं :

$ ( dd bs=1131 count=1 of=dev_null && dd bs=4K of=out.mp3 ) < 100827_MR029_LobbyControl.mp3
1+0 records in
1+0 records out
1131 bytes (1.1 kB) copied, 7.9691e-05 s, 14.2 MB/s
22433+1 records in
22433+1 records out
91886130 bytes (92 MB) copied, 0.329823 s, 279 MB/s
$ ls -l *
-rw------- 1 max users 91887261 2011-02-03 22:59 100827_MR029_LobbyControl.mp3
-rw-r--r-- 1 max users     1131 2011-02-03 23:04 dev_null
-rw-r--r-- 1 max users 91886130 2011-02-03 23:04 out.mp3
$ cat dev_null out.mp3 > orig
$ cmp 100827_MR029_LobbyControl.mp3 orig

1
धन्यवाद - मुझे नहीं पता था कि पाइप्ड इनपुट उस तरह की दूसरी प्रक्रिया को जारी रखता है, मुझे लगता है कि यह सब शेल है? मुझे निश्चित रूप से याद होगा! मैंने मार्को को टिक दिया है क्योंकि वह पहले यहां मिला था, लेकिन +1 और उत्तर के लिए धन्यवाद!
रूप

1
@Rup, हाँ, उप-शेल - कोष्ठकों के माध्यम से बनाया गया - एक स्टडिन फाइल डिस्क्रिप्टर प्रदान करता है और दोनों dd कॉल क्रमिक रूप से इनपुट का उपभोग करते हैं। हाँ - मार्को ने मुझे 29 सेकंड से हराया :)
maxschlepzig

6

यदि फाइलसिस्टम और लिनक्स कर्नेल इसे सपोर्ट करते हैं तो आप कोशिश कर सकते हैं fallocateकि आप इनकम में बदलाव करना चाहते हैं: सबसे अच्छी स्थिति में कोई डेटा आईओ नहीं है:

$ fallocate <magic> -o 0 -l 1131 inplace.dump

जहां <magic>फाइलसिस्टम, लिनक्स संस्करण और फ़ाइल प्रकार ( FALLOC_FL_COLLAPSE_RANGEया FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZEआंतरिक रूप से इस्तेमाल किया जा सकता है ) पर निर्भर करता है ।


1
यह मेरा पसंदीदा तरीका है, लेकिन एक कंटेनर में इसे चलाने के अपने मुद्दे हैं। stackoverflow.com/questions/31155591/…
michaelcurry

3

आप का उपयोग करना चाहिए count=0- lseek()जब भी संभव है कि एक सरल है।

ऐशे ही:

{  dd bs=1131 skip=1 count=0; cat; } <filtered.dump >trimmed.dump

ddहोगा lseek()ऑफसेट एक 1131 बाइट के लिए इनपुट फ़ाइल वर्णनकर्ता, और फिर catबस कॉपी करेगा जो उत्पादन के लिए बनी हुई है।


2

फिर भी (का उपयोग किए बिना एक फ़ाइल से अग्रणी बाइट्स को दूर करने का एक और तरीका ddबिल्कुल) का उपयोग करने के लिए है xxdऔर sedया tailक्रमशः।

bytes=$((1131*2))

xxd -p -c 256 filtered.dump | tr -d '\n' | sed "s/^.\{0,${bytes}\}//" | xxd -r -p > trimmed.dump

bytes=$((bytes + 1)) 
xxd -p -c 256 filtered.dump | tr -d '\n' | tail -c +${bytes} | xxd -r -p > trimmed.dump

यह साफ-सुथरा है, लेकिन मुझे लगता है कि मैं फ़ाइल को बाइनरी में फाइल के साथ काम करना पसंद करता हूं, बजाय इसे हेक्स से और कन्वर्ट करने के।
Rup

2

@maxschlepzig एक ऑनलाइन लाइनर के लिए पूछता है। यहाँ एक perl में है। यह 2 तर्क लेता है: बाइट और लंबाई से। इनपुट फ़ाइल '<' द्वारा दी जानी चाहिए और आउटपुट स्टडआउट पर होगा:

perl -e 'sysseek(STDIN,shift,0) || die; $left = shift;
     while($read = sysread(STDIN,$buf, ($left > 32768 ? 32768 : $left))){
        $left -= $read; syswrite(STDOUT,$buf);
     }' 12345678901 19876543212 < bigfile > outfile

यदि लंबाई फ़ाइल से बड़ी है, तो शेष फ़ाइल की प्रतिलिपि बनाई जाएगी।

मेरे सिस्टम पर यह 3.5 जीबी / एस बचाता है।


मुझे लगता है कि उनकी एक-पंक्ति चुनौती आपको यह साबित करने के लिए मिली थी कि स्क्रिप्टिंग भाषा समाधान हालांकि उनके एक-लाइन शेल समाधान से बेहतर था। और मैं उसे पसंद करता हूं: यह मेरे लिए छोटा और स्पष्ट है। अगर आपका बेहतर प्रदर्शन करता है, क्योंकि आप उससे बड़े ब्लॉक आकार का उपयोग कर रहे हैं, जो उसके संस्करण में भी आसानी से हो जाता है।
रूप

@Rup Alas, लेकिन नहीं। आप भूल जाते हैं कि ddएक पूर्ण पढ़ने की गारंटी नहीं है। कोशिश: हाँ | dd bs = 1024 k गिनती = 10 | wc unix.stackexchange.com/questions/17295/…
Ole Tange

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