किसी फ़ाइल का inplace modification कैसे किया जा रहा है?


10

क्या एक फ़ाइल जैसे के माध्यम से की "inplace" संशोधन करता है sed -iया perl -iमतलब?
मेरा सवाल यह है कि यह इनफ्लाइट मॉडिफिकेशन कैसे किया जाता है। क्या फ़ाइल की प्रतिलिपि बनाई गई प्रति में संशोधन किया गया है और फिर मूल को बदल दिया गया है? या मूल फ़ाइल किसी तरह जगह में संशोधित किया जा रहा है?


इस विषय के विस्तृत विवरण के लिए backreference.org/2011/01/29/in-place-editing-of-files पर एक नज़र डालें ।
scy

उस मामले के लिए, यह कैसे किया जाता है exया vi?
वाइल्डकार्ड

@Wildcard - उनमें से प्रत्येक में एक पूरी प्रणाली है। exएक मेलफ़ाइल बनाए रखता है (जैसे, dead.mailया आप में कुछ , या आपके मेल स्पूलर के पास कहीं और, आमतौर पर) । चश्मे की जांच करें - उनमें से प्रत्येक ने बड़ी लंबाई के लिए परिभाषित किया है ... exज्यादातर मामलों में इसका अपना द्विआधारी प्रारूप है (आपकी -rescueफ़ाइल को देखें) और इसका उपयोग अलग-अलग अस्थायी बफर फ़ाइलों (संभवत: छह के रूप में) को अलग करने के लिए किया जाता है । इसलिए इन बफ़र्स को संपादित करने के लिए इनपुट के ब्लॉक को कॉपी करके प्रति परिवर्तन ऑफ़सेट में लिखते हैं :!written?
mikeserv

जवाबों:


18

sed एक अस्थायी फ़ाइल बनाता है, उस फ़ाइल में आउटपुट लिखता है, और फिर मूल के शीर्ष पर अस्थायी फ़ाइल का नाम बदल देता है।

आप देख सकते हैं कि क्या होता है strace:

$ strace -e trace=file sed -i -e '' a
execve("/usr/bin/sed", ["sed", "-i", "-e", "", "a"], [/* 34 vars */]) = 0
<...trimmed...>
open("a", O_RDONLY)                     = 3
open("./sedxvhRY8", O_RDWR|O_CREAT|O_EXCL, 0600) = 4
rename("./sedxvhRY8", "a")              = 0
+++ exited with 0 +++

यह सभी फ़ाइल संचालन को लॉग sedकरता है: यह एक नई फ़ाइल बनाता है (सुरक्षित रूप से O_CREAT|O_EXCL), इसमें डेटा लिखता है, और फिर इसे मेरी मूल फ़ाइल के शीर्ष पर वापस ले जाता है a

sed -iबैकअप के लिए उपयोग करने के लिए एक प्रत्यय स्वीकार करता है, और उस स्थिति में यह मूल को पहले (शीर्ष पर नाम बदलने के बजाय) बाहर ले जाता है। अधिकांश बीएसडी sedएस में यह तर्क अनिवार्य है । इस स्थिति में, संक्षिप्त समय है जब निर्देशिका में सही नाम से कोई फ़ाइल नहीं है।

perl हाल के संस्करणों में इनपुट फ़ाइल को खोलता है, फिर उसे हटाता है और उसी नाम से एक नई फ़ाइल बनाता है:

open("a", O_RDONLY)               = 3
unlink("a")                       = 0
open("a", O_WRONLY|O_CREAT|O_EXCL, 0600) = 4

जब आप unlinkकिसी फ़ाइल को हटाते हैं ( ) तो आपके पास पहले से खुला हुआ है तो आप उस तक पहुंच बनाए रख सकते हैं जब तक आप उसके चारों ओर हैंडल रखते हैं, इसलिए वह डिलीट हुई फ़ाइल से डेटा को पढ़ता रह सकता है। इस तरह perlएक अस्थायी फ़ाइल के बजाय सीधे आउटपुट फ़ाइल में लिखता है: कोई अतिरिक्त फ़ाइल नहीं बनाई गई है, लेकिन यदि आप प्रक्रिया के दौरान फ़ाइल पढ़ते हैं, तो आपको आंशिक सामग्री मिलेगी, इसके विपरीत sed। एक संक्षिप्त समय भी होता है जब सही नाम के साथ कोई फ़ाइल नहीं होती है, जो कि अंत (जैसा कि sed -i .bak) के बजाय प्रक्रिया की शुरुआत में है ।


दोनों sedऔर perlहोगा:

  • एक साधारण फ़ाइल के साथ एक प्रतीकात्मक लिंक बदलें।
  • कड़ी कड़ी तोड़ो।
  • यदि संभव हो तो समूह का स्वामित्व सुरक्षित रखें।
  • फ़ाइल को अपने डिफ़ॉल्ट समूह (या मूल निर्देशिका के समूह के साथ बनाएं अगर उस निर्देशिका में setgidबिट है) यदि वह उस समूह के स्वामित्व में थी जो आप में नहीं हैं और आप जड़ नहीं हैं।
  • यदि आप रूट हैं तो फ़ाइल स्वामित्व सुरक्षित रखें।
  • बुनियादी अनुमतियाँ संरक्षित करें।
  • संरक्षित setuidऔर setgrpबिट्स, यदि परिणामी समूह उसी समूह के समान है जो इसमें शुरू हुआ था।
  • चिपचिपा सा संरक्षित करें।
  • Xattrs संरक्षित नहीं है।

sed मर्जी:

  • ACLs को संरक्षित करें (लिनक्स पर; मैं दूसरों के बारे में नहीं जानता)

perl मर्जी:

  • एसीएल का संरक्षण नहीं

उपरोक्त जीएनयू sedऔर मैक ओएस एक्स के साथ लिनक्स पर सच है (फ्रीबीएसडी-व्युत्पन्न) sed


3

@ होमर के उत्तर के अतिरिक्त, से perldoc perlrun:

निर्दिष्ट करता है कि "<>" निर्माण द्वारा संसाधित की गई फ़ाइलों को जगह-जगह संपादित किया जाना है। यह इनपुट फ़ाइल का नाम बदलकर, आउटपुट फ़ाइल को मूल नाम से खोलता है, और प्रिंट के लिए डिफ़ॉल्ट के रूप में उस आउटपुट फ़ाइल का चयन करता है () कथन। यदि इन नियमों का पालन करते हुए विस्तार किया जाता है, तो पुरानी फ़ाइल के नाम को संशोधित करने के लिए बैकअप कॉपी बनाने के लिए उपयोग किया जाता है:

यदि कोई एक्सटेंशन नहीं दिया गया है, तो कोई बैकअप नहीं बनाया गया है और वर्तमान फ़ाइल ओवरराइट की गई है।

यदि एक्सटेंशन में * नहीं है, तो इसे प्रत्यय के रूप में वर्तमान फ़ाइल नाम के अंत में जोड़ा जाता है। यदि एक्सटेंशन में एक या अधिक * वर्ण होते हैं, तो प्रत्येक * को वर्तमान फ़ाइल नाम से बदल दिया जाता है।

और याद रखें कि, कोई सॉफ्ट लिंक या हार्ड लिंक संरक्षित नहीं है:

ध्यान दें कि क्योंकि -i एक ही नाम की नई फ़ाइल बनाने से पहले मूल फ़ाइल का नाम बदल देता है या हटा देता है, UNIX- शैली नरम और हार्ड लिंक संरक्षित नहीं किए जाएंगे।

अंत में, -i स्विच निष्पादन को बाधित नहीं करता है जब कमांड लाइन पर कोई फाइल नहीं दी जाती है। इस स्थिति में, कोई बैकअप नहीं बनाया जाता है (मूल फ़ाइल निश्चित रूप से निर्धारित नहीं की जा सकती है) और प्रसंस्करण आय STDIN से STDOUT तक हो सकती है जैसा कि उम्मीद की जा सकती है।

यह भी बताता है कि क्यों आप का उपयोग करना चाहिए -iसाथ -p, विकल्प या एक स्पष्ट का उपयोग printबयान करता है, तो आप के साथ संपादित inplace करना चाहते हैं perl:

# Opps, file will be truncated, becomes empty
$ perl -i.bak -ne 's/123/qwe/' file

# Right way
$ perl -i.bak -ne 's/123/qwe/;print' file

# Or
$ perl -i.bak -pe 's/123/qwe/' file
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.