क्या पेर्ल बनाने का एक तरीका है-मैं क्लोबर सिम्बलिंक नहीं करता?


12

मेरा एक दोस्त बताता है कि यदि आप करते हैं:

perl -pi.bak -e 's/foo/bar/' somefile

जब "somefile" वास्तव में एक सिम्लिंक होता है, तो perl वही करता है जो डॉक्स कहता है कि यह करेगा:

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

जो अपरिवर्तित वास्तविक फ़ाइल की ओर इशारा करते हुए एक नए सिम्कलिन "somefile.bak" के परिणामस्वरूप होता है, और एक नया, नियमित फ़ाइल "somefile" को परिवर्तनों के साथ बदल देता है।

कई मामलों में, सीलिंक का अनुसरण करना वांछित व्यवहार होगा (भले ही यह .bak फ़ाइल अस्पष्ट का सही स्थान छोड़ता है)। क्या एक सरल तरीका यह है कि एक रैपर में सिम्बल के परीक्षण के अलावा और उचित तरीके से मामले को संभालने के लिए?

( sedवही काम करता है, जो इसके लायक है।)


1
कॉल विम या एमएसीएस (मुझे लगता है कि दोनों सहानुभूति का पालन करते हैं)? गंभीरता से, मुझे डर है कि उत्तर -p -iआपकी स्क्रिप्ट में फिर से लागू हो जाएगा।
गिलेस एसओ- बुराई को रोकना '

सिड वास्तव में एक ही चीज़ नहीं करता है, कम से कम 4.2.1 संस्करण के बाद से नहीं, 2009 के जून में जारी किया गया। आपको लिंक को संपादित करने के लिए - समोइंल को क्लॉब करने के बजाए संपादित करने के लिए --follow-symlinks विकल्प को शामिल करना होगा। ; मुझे लगता है कि यह मौजूदा लिपियों के टूटने से बचने के लिए किया गया था जो पुराने व्यवहार पर निर्भर हो सकता है।
गैरेट

जवाबों:


6

मुझे आश्चर्य है कि क्या छोटे spongeसामान्य प्रयोजन उपयोगिता ("मानक इनपुट को सोखें और फाइल में लिखें") इस मामले में सहायक होगा और क्या यह सिम्लिंक का पालन करेगा।

लेखक इस तरह का वर्णन करता sponge है:

यह फाइल को इन-प्लेस के साथ-साथ यूनिक्स टूल्स में एडिट करने की समस्या को दूर करता है, अर्थात यदि आप उस फाइल को रीडायरेक्ट करते हैं जिसे आप एडिट करने की कोशिश कर रहे हैं तो रीडायरेक्शन प्रभावी होता है (फाइल की सामग्री को क्लॉबरिंग करते हुए) पाइप लाइन में पहले कमांड से पहले। फ़ाइल से पढ़ने के लिए गोल हो जाता है। इस तरह से स्विच करता है sed -iऔर इसके perl -iचारों ओर काम करता है, लेकिन हर कमांड जिसे आप पाइपलाइन में उपयोग करना चाहते हैं, ऐसा विकल्प नहीं हो सकता है, और आप वैसे भी कई-कमांड पाइपलाइनों के साथ उस दृष्टिकोण का उपयोग नहीं कर सकते हैं।

मैं आमतौर पर स्पंज का उपयोग इस तरह से करता हूं:

sed '...' file | grep '...' | sponge file

अरे शांत, वह काम करता है। मुझे संदेह है कि ऊपर दिए गए गाइल्स की टिप्पणी "वास्तविक" उत्तर है, लेकिन चूंकि उसने इसे एक उत्तर के रूप में नहीं बनाया है, और जब से मैंने एक नई उपयोगिता सीखी है, मैं इसे ले लूंगा। :)
Mattdm

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

- हां, मैंने जवाब देने से पहले कोशिश की। जब fileआपके उदाहरण में ऊपर एक सिम्लिंक है, तो लिंक अकेला रह गया है और वास्तविक फ़ाइल बदल गई है।
Mattdm

@mattdm: हाँ, पुष्टि के लिए धन्यवाद! (मैंने आपके शब्दों पर ध्यान दिया जो "काम करता है" थोड़ी देर बाद मैंने अपनी टिप्पणी लिखी।)
imz - Ivan Zakharyaschev

3

यदि आप एक ऐसे तथ्य के लिए जानते हैं जो somefileएक सिमलिंक है, तो आप निम्नलिखित के साथ फाइल करने के लिए स्पष्ट रूप से पूर्ण पथ की आपूर्ति कर सकते हैं:

perl -pi.bak -e 's/foo/bar/' $(readlink somefile)

इस तरह, मूल सिम्कलिन बरकरार रहता है क्योंकि प्रतिस्थापन अब सीधे मूल फ़ाइल के साथ किया जाता है।


लेकिन readlinkहो सकता है कि आउटपुट अभी भी एक और सिमिंक हो। बेस्ट उपयोग करने के लिए किया जाएगा -fया -eजहां उपलब्ध हो या zshकी $file:Pया (:P)क्वालीफायर glob के रूप में @ikegami द्वारा दिखाए गए एक सिमलिंक मुक्त पथ प्राप्त करने के लिए।
स्टीफन चेज़लस

3

यदि आप एक एकल फ़ाइल के साथ काम कर रहे हैं, तो कमांड निम्नानुसार दिखाई देगी:

perl -i -pe'...' -- "$qfn"

समाधान तो निम्नलिखित है:

perl -i -pe'...' -- "$( readlink -e -- "$qfn" )"

यह सहानुभूति और गैर-सहानुभूति दोनों को संभालता है।


यदि आप एक बड़ी संख्या में फ़ाइलों के साथ काम कर रहे हैं, तो कमांड निम्नानुसार दिखाई देगी:

... | xargs -r perl -i -pe'...' --

समाधान तो निम्नलिखित है:

... | xargs -r readlink -ze -- | xargs -r0 perl -i -pe'...' --

यह सहानुभूति और गैर-सहानुभूति दोनों को संभालता है।


कैविएट readlink एक मानक कमांड नहीं है, इसलिए यह उपस्थिति, इसके तर्क और इसकी कार्यक्षमता प्रणाली द्वारा भिन्न होती है, इसलिए अपने दस्तावेज़ की जांच करना सुनिश्चित करें। उदाहरण के लिए, कुछ कार्यान्वयन हैं -f(जो आप यहां भी उपयोग कर सकते हैं), लेकिन नहीं -e, कुछ भी नहीं । busybox'एस readlink -fजीएनयू की तरह बर्ताव करती है readlink -e। और कुछ सिस्टम में एक realpathकमांड है readlinkजिसके बजाय आम तौर पर GNU की तरह व्यवहार किया जाता है readlink -f

जीएनयू से सावधान रहें readlink -e, जो सिम्बलिंक्स को मौजूदा फाइल में हल नहीं किया जा सकता है उन्हें चुपचाप हटा दिया जाता है।


@ स्टीफन चेज़लस, $var:Pमेरे लिए काम नहीं करता है। ( X='tmp' zsh -c 'perl -E"say for @ARGV" $X:P'आउटपुट tmp:P)
ikegami

आपको zsh 5.3 (2016) या इसके बाद के संस्करण की आवश्यकता है $var:P। पुराने संस्करणों के साथ, आप $var:Aइसके बजाय हमेशा उपयोग कर सकते हैं । मतभेदों के लिए मैनुअल देखें और परिचय (वास्तविक इंटरफ़ेस) के लिए तर्क के लिए zsh.org/mla/users/2016/msg00593.html देखें । :Prealpath()
स्टीफन चेजलस

( 2012 :Aमें 4.3.10 (2009), GNU readlink -zमें जोड़ा गया था , मैं किसी भी अन्य readlinkकार्यान्वयन के बारे में नहीं जानता जो समर्थन करता है -z)। ध्यान दें कि जीएनयू के साथ xargs, आप आम तौर पर -rविकल्प चाहते हैं जब तक आप गारंटी नहीं दे सकते कि इनपुट खाली नहीं होगा। यहाँ, यह कोई बड़ी बात नहीं है (जब तक कि perlकोड BEGIN/ ENDकथन शामिल नहीं है), आपको बस एक -i used with no filenames on the command line, reading from STDIN.चेतावनी मिलेगी यदि ऐसा होता है।
स्टीफन चेजलस

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