फ़ाइलों के पहले n बाइट्स हटाएँ


32

मुझे एक अत्यधिक समस्या हो गई है, और मेरे द्वारा हल किए जाने वाले सभी समाधान जटिल हैं। मेरे UNIX / Linux अनुभव के अनुसार एक आसान तरीका होना चाहिए।

मैं प्रत्येक फ़ाइल के पहले 31 बाइट्स को हटाना चाहता हूँ /foo/। प्रत्येक फ़ाइल काफी लंबी है। ठीक है, मुझे यकीन है कि कोई मुझे बहुत ही आसान समाधान प्रदान करेगा जिसकी मैं कल्पना नहीं कर सकता। शायद जाग गया?


2
कोई भी awk / sed / ed सॉल्यूशन लाइन-ओरिएंटेड होगा, इसलिए यदि आपको पता नहीं है कि पहली लाइन कम से कम 31 वर्ण की होगी तो जटिलताएं उत्पन्न होंगी।
ग्लेन जैकमैन

जवाबों:


28
for file in /foo/*
do
  if [ -f "$file" ]
  then
    dd if="$file" of="$file.truncated" bs=31 skip=1 && mv "$file.truncated" "$file"
  fi
done

या तेजी से, गिल्स के सुझाव के लिए धन्यवाद:

for file in /foo/*
    do
      if [ -f $file ]
      then
        tail +32c $file > $file.truncated && mv $file.truncated $file
      fi
    done

नोट: पॉज़िक्स पूंछ "+-32 सी" के बजाय "-c +32" निर्दिष्ट करती है, लेकिन सोलारिस डिफ़ॉल्ट पूंछ इसे पसंद नहीं करती है:

   $ /usr/bin/tail -c +32 /tmp/foo > /tmp/foo1
    tail: cannot open input

/usr/xpg4/bin/tail दोनों वाक्यविन्यास के साथ ठीक है।


1
ddयहाँ पर सुझाव देना tailअधिक कठिन है, अधिक उपयुक्त है (सरल टाइप करें, हत्यारे टाइपो का जोखिम कम है, स्टैडर पर कोई सहज संदेश नहीं)।
गिलेस एसओ- बुराई को रोकना '27

तुम सही हो। मैं आमतौर पर पाठ फ़ाइलों को संसाधित करने के लिए इच्छित कमांड से बचता हूं जब संभवतः बाइनरी वाले प्रसंस्करण करते हैं लेकिन "टेल + 32 सी" यहां काम करेगा।
जलीगेरे

1
@ जेलीग्रे: आपने लिखा है cut (कि पूंछ नहीं होनी चाहिए? एसिस, यह मेरे लिए काम नहीं करता है ...
पीटर

बेशक, यह पूंछ है। बेमेल के बारे में क्षमा करें।
जलीगेरे

@jlliagre: सोलारिस पर, आप होना चाहिए /usr/xpg4/binके आगे /usr/binअपने पर PATH, या आप 1990 के दशक में अटक हो जाएगा। कई यूनियनों (जैसे जीएनयू, बिजीबॉक्स) अब ऐतिहासिक +32cवाक्यविन्यास का समर्थन नहीं करते हैं , और इसका अर्थ है एक फ़ाइल जिसे +32cपोसिक्स की आवश्यकता है) कहा जाता है ।
गिल्स एसओ- बुराई को रोकना '28

12

निम्नलिखित आदेशों ने पहले 31 बाइट्स में कटौती की $file( $file~एक अस्थायी प्रतिलिपि के रूप में उपयोग करके )।

dd if="$file" of="$file~" bs=1 skip=31
mv "$file~" "$file"

आपको केवल ऊपर या findनीचे की सभी फाइलों को सूचीबद्ध करने /foo/और हर मिलने के लिए दोनों को निष्पादित करने की आवश्यकता $fileहै।


1
स्वैपिंग bs और स्किप वैल्यू से प्रदर्शन बढ़ेगा।
जलीगेरे

10

tail -c +32पहले 31 बाइट्स में इसके इनपुट माइनस को आउटपुट करता है। (हाँ, तर्क एक बंद है।) किसी स्थान पर फ़ाइल को संपादित करने के लिए, लूप में स्पंज का उपयोग करें , या यदि आपके पास नहीं है और परेशान नहीं करना चाहते हैं, तो शेल में अपना काम करें:

for x in /foo/*; do tail -c +32 "$x" | sponge "$x"; done
for x in /foo/*; do tail -c +32 "$x" >"$x.new" && mv "$x.new" "$x"; done

यदि किसी भी कारण से कमांड को बाधित किया जाता है (जैसे कि एक बिजली की विफलता), तो यह पता लगाना मुश्किल हो सकता है कि आपने कहाँ छोड़ा था। एक नई निर्देशिका को अलग निर्देशिका में लिखने से चीजें आसान होंगी।

mkdir /foo.tmp
cd /foo
for x in *; do tail -c +42 -- "$x" >"/foo.tmp/$x" && rm -- "$x"; done
mv /foo.tmp/* /foo
rmdir /foo.tmp

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


2

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

for each in /foo/*
do
  ex -sc '%!tail -c+32' -cx "$each"
done
  1. % सभी लाइनों का चयन करें

  2. ! चलाने के आदेश

  3. x सहेजें और बंद करें

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