फ़ाइल को बदलते समय फ़ाइल अनुमतियों को बनाए रखें (या पुनर्स्थापित करें)


11

मेरे पास एक कमांड है जो एक फ़ाइल को एक तर्क के रूप में स्वीकार करता है, फ़ाइल को संशोधित करता है, फिर इसे दूसरे तर्क में निर्दिष्ट फ़ाइल नाम पर लिखता है। मैं उस कार्यक्रम को बुलाऊंगा modifyfile

मैं चाहता था कि यह "जगह पर" काम करे इसलिए मैंने एक शेल स्क्रिप्ट (बैश) लिखी जो इसे एक अस्थायी फ़ाइल में संशोधित करता है और फिर इसे स्थानांतरित करता है:

TMP=`mktemp`
modifyfile "$original" "$TMP"
mv -v "$TMP" "$original"

इस फ़ाइल पर अनुमतियों को नष्ट करने का दुर्भाग्यपूर्ण दुष्प्रभाव है। फ़ाइल डिफ़ॉल्ट अनुमतियों के साथ फिर से बनाई जाती है।

क्या mvअपनी अनुमति में बदलाव किए बिना गंतव्य को अधिलेखित करने के लिए कमांड को बताने का एक तरीका है ? या वैकल्पिक रूप से उपयोगकर्ता, समूह, और अनुमतियों को मूल से बचाने और उन्हें पुनर्स्थापित करने का एक तरीका है?

जवाबों:


10

उपयोग करने के बजाय mv, बस पुनर्निर्देशित करें cat। उदाहरण के लिए:

TMP=$(mktemp)
modifyfile "$original" "$TMP"
cat "$TMP" > "$original"

यह फ़ाइल स्तर पर कुछ भी छुए बिना, $originalसामग्री के साथ ओवरराइट $TMPकरता है।


यदि कुछ प्रोग्राम में फ़ाइल को एक ओपन फ़ाइल हैंडल है तो क्या यह समस्याग्रस्त नहीं हो सकता है?
मार्टिन वॉन विटिच

2
मुझे तब भी rm "$TMP"उतना ही अच्छा लगता है, लेकिन ऐसा लगता है कि जैसा मैं चाहता हूं वैसा ही करूंगा।
स्टीफन ओस्टरमिलर

यदि आप mvइसके बजाय उपयोग कर रहे थे तो @MartinvonWittich यह एक समस्या होगी । मुझे उस समस्या को हल करने का कोई रास्ता नहीं दिख रहा है।

2
@MartinvonWittich हाँ। क्रिएट-न्यू-तब-मूव आपको एक परमाणु परिवर्तन देता है और उन प्रोग्रामों को प्रभावित नहीं करता है जिनमें फ़ाइल खुली होती है, लेकिन चूंकि यह एक नई फ़ाइल बनाता है फ़ाइल का स्वामित्व और अनुमतियां खो जाती हैं। Truncate-मौजूदा-तब-लेखन अनुमतियाँ और स्वामित्व सुरक्षित रखता है, लेकिन क्रैश की स्थिति में डेटा खो देता है और उन प्रोग्रामों के पैरों के नीचे गलीचा को स्वाइप करता है जिनके पास फ़ाइल खुली है। आप दोनों के अच्छे हिस्सों को जोड़ नहीं सकते।
गिलेस एसओ- बुराई को रोकना '

1
@MartinvonWittich chownकेवल रूट के रूप में काम करता है। chmodऔर chgrpउपयोगकर्ता की अनुमति के आधार पर काम कर सकता है या नहीं। न ही अन्य विशेषताओं जैसे एसीएल या फाइलसिस्टम-विशिष्ट विस्तारित विशेषताओं की प्रतिलिपि बनाता है।
गिल्स एसओ- बुराई को रोकें '

10

फ़ाइल को नए संस्करण द्वारा प्रतिस्थापित करने के लिए दो रणनीतियाँ हैं:

  1. नए संस्करण के साथ एक अस्थायी फ़ाइल बनाएं, फिर इसे जगह में ले जाएं।

    • लाभ: यदि कोई प्रोग्राम उस फाइल को खोलता है, तो वह या तो पुरानी सामग्री या नई सामग्री को पढ़ेगा, यह इस बात पर निर्भर करता है कि उसने इस कदम से पहले या बाद में फाइल को खोला है या नहीं। कोई मिक्स-अप नहीं है।
    • लाभ: दुर्घटना के मामले में, पुरानी सामग्री संरक्षित है।
    • नकारात्मक पक्ष: चूंकि एक नई फ़ाइल बन जाती है, फ़ाइल की विशेषताएँ (स्वामित्व, अनुमति, आदि) संरक्षित नहीं हैं।
  2. जगह में पुरानी फाइल को अधिलेखित करें।

    • लाभ: फ़ाइल की विशेषताएँ संरक्षित हैं।
    • डाउनसाइड: क्रैश की स्थिति में, फ़ाइल को आधा लिखा जा सकता है।
    • डाउनसाइड: यदि किसी प्रोग्राम में फ़ाइल तब खुली होती है जब उसे अपडेट किया जा रहा हो, तो यह प्रोग्राम असंगत डेटा को पढ़ सकता है।

यदि आप कर सकते हैं, तो विधि 1 का उपयोग करें, लेकिन पहले मूल फ़ाइल की विशेषताओं को दोहराएं cp -p --attributes-only। इसके लिए जीएनयू कोर्यूटिल्स (यानी गैर-एम्बेडेड लिनक्स, या पर्याप्त रूप से लिनक्स जैसे वातावरण) की आवश्यकता होती है। यदि आपके cpपास नहीं है --attributes-only, तो इस विकल्प को छोड़ दें: यह काम करेगा लेकिन यह डेटा को भी दोहराएगा।

tmp=$(mktemp)
cp -p --attributes-only "$original" "$tmp"
modifyfile "$original" "$tmp"
mv -f "$tmp" "$original"

यदि आप मौजूदा फ़ाइल की विशेषताओं को नहीं दोहरा सकते हैं, उदाहरण के लिए, क्योंकि आपके पास इस पर अनुमतियाँ हैं, लेकिन इसके स्वामी नहीं हैं और आप स्वामी को संरक्षित करना चाहते हैं, तो केवल विधि 2 संभव है। डेटा हानि के जोखिम को कम करने के लिए:

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

tmp=$(mktemp)
backup="${original}~"
modifyfile "$original" "$tmp"
cp -p "$original" "$backup"
cp -f "$tmp" "$original"

अच्छा उत्तर! आजकल मैं तर्क का उपयोग करने का सुझाव दूंगा - केवल विधि 1 में cp कमांड के साथ । इस तरह, फ़ाइल की सामग्री की प्रतिलिपि बनाने के लिए संसाधनों का उपयोग नहीं करेगा। मुझे नहीं पता चल पाया कि यह तर्क किस संस्करण से जोड़ा गया है। cp -p --attributes-only "$original" "$tmp"
मार्सेलो बैरोस

@MarceloBarros यह GNU coreutils 8.6 में 2010-10-15 को जारी किया गया था, इसलिए इन दिनों यदि आपके पास GNU कोरुटील्स हैं तो आपके पास होना चाहिए। अन्य cpकार्यान्वयन के साथ अभी भी ऐसी कोई बात नहीं है।
गाइल्स का SO- बुराई पर रोक '14

5

पहले उत्तर पर हमारी चर्चा के बाद, मैं एक अलग उत्तर का प्रस्ताव करता हूं:

TMP="$(mktemp "$original".XXXXXXXXXX)"
modifyfile "$original" "$TMP"
chmod --reference="$original" "$TMP"
chown --reference="$original" "$TMP"
mv -f "$TMP" "$original"

टिप्पणियों:

  • मैं यह सुनिश्चित करने के लिए टेम्पलेट $originalमें उपयोग करता हूं mktempकि अस्थायी फ़ाइल को /tmpउसी फ़ोल्डर में नहीं रखा गया है $original। मेरा मानना ​​है कि अगर /tmpएक अलग फाइल सिस्टम पर मुहिम शुरू की जाए तो ऑपरेशन परमाणु नहीं होगा।
  • इसका परिणाम mktempअब व्हाट्सएप के मामले में है।
  • मैं $()`` के बजाय उपयोग करता हूं क्योंकि मैं इसे क्लीनर मानता हूं।
  • ch{mod,own} --referenceकी अनुमतियों को स्थानांतरित करने के लिए उपयोग किया जाता $originalहै $TMP। यदि किसी के पास अतिरिक्त विचार हैं कि मेटाडेटा क्या हो सकता है और उसे स्थानांतरित किया जाना चाहिए, तो कृपया मेरी पोस्ट को संपादित करें और इसे जोड़ें।
  • ओह ठीक है, इसके लिए रूट अनुमति की आवश्यकता है क्योंकि गिल्स ने बताया। खैर, अब मैं इसे खारिज नहीं करने जा रहा हूं कि मैंने इसे लिखा है: पी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.