जब लक्ष्य फ़ाइल अभी तक मौजूद नहीं है, तो '>' के बराबर `> के साथ पुनर्निर्देशन है?


80

बैश या श की तरह एक शेल पर विचार करें। लक्ष्य फ़ाइल मौजूद होने पर किसी मामले में स्वयं के बीच मूल अंतर >और >>प्रकट होता है:

  • > फ़ाइल को शून्य आकार में काटता है, फिर लिखता है;
  • >> यह छोटा नहीं है, यह फ़ाइल के अंत में लिखता है (जोड़ता है)।

यदि फ़ाइल मौजूद नहीं है, तो इसे शून्य आकार के साथ बनाया गया है; फिर को लिखा गया। यह दोनों ऑपरेटरों के लिए सही है। ऐसा लगता है कि ऑपरेटर तब बराबर होते हैं जब लक्ष्य फ़ाइल अभी तक मौजूद नहीं है।

क्या वे वास्तव में हैं?

जवाबों:


107

tl; डॉ

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


पूरा जवाब

(नोट: डेबियन जीएनयू / लिनक्स 9 पर किए गए मेरे सभी परीक्षण)।

एक और अंतर

नहीं, वे समकक्ष नहीं हैं। एक और अंतर है। यह स्वयं प्रकट हो सकता है कि लक्ष्य फ़ाइल पहले मौजूद थी या नहीं।

यह निरीक्षण करने के लिए, एक प्रक्रिया है कि डेटा उत्पन्न करता है चलाने के लिए और के साथ एक फ़ाइल को अनुप्रेषित >या >>(जैसे pv -L 10k /dev/urandom > blob)। इसे चलाने दें और फ़ाइल का आकार बदलें (जैसे कि truncate)। आप देखेंगे कि >इसकी (बढ़ती) ऑफसेट होती रहती है जबकि >>हमेशा अंत तक बनी रहती है।

  • यदि आप फ़ाइल को छोटे आकार में काटते हैं (यह शून्य आकार हो सकता है)
    • >परवाह नहीं करेगा, यह अपनी इच्छित ऑफसेट पर लिखेगा जैसे कि कुछ भी नहीं हुआ; ट्रंकिंग के बाद ही ऑफ़सेट फ़ाइल के अंत से परे होता है, इससे फ़ाइल अपने पुराने आकार को पुनः प्राप्त कर लेगी और आगे बढ़ जाएगी, लापता डेटा शून्य (एक विरल तरीके से, यदि संभव हो) से भर जाएगा;
    • >> नए सिरे से जुड़ जाएगा, फ़ाइल अपने छोटे आकार से बढ़ेगी।
  • यदि आप फ़ाइल को बड़ा करते हैं
    • >परवाह नहीं करेगा, यह अपनी इच्छित ऑफसेट पर लिखेगा जैसे कि कुछ भी नहीं हुआ; बस आकार बदलने के बाद ऑफसेट फ़ाइल के अंदर कहीं है, यह फ़ाइल को थोड़ी देर के लिए बढ़ने से रोक देगा, जब तक ऑफसेट नए सिरे तक नहीं पहुंचता है, तब फ़ाइल सामान्य रूप से बढ़ेगी;
    • >> नए सिरे से जुड़ जाएगा, फ़ाइल अपने बढ़े हुए आकार से बढ़ जाएगी।

एक और उदाहरण है >>जब डेटा जेनरेट करने की प्रक्रिया चल रही हो और फ़ाइल में लिखी जा रही हो (एक अलग से ) कुछ अतिरिक्त। यह फ़ाइल को बड़ा करने के समान है।

  • इसके साथ जेनरेट करने की प्रक्रिया >अपने इच्छित ऑफसेट पर लिखेगी और अंततः अतिरिक्त डेटा को ओवरराइट कर देगी।
  • इसके साथ जेनरेट करने की प्रक्रिया >>नए डेटा को छोड़ देगी और इसे अतीत में जोड़ देगी (दौड़ की स्थिति हो सकती है, दो धाराएं आपस में जुड़ सकती हैं, फिर भी कोई डेटा ओवरराइट नहीं किया जाना चाहिए)।

उदाहरण

क्या यह व्यवहार में मायने रखता है? नहीं है इस सवाल :

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

यह उत्तर कहता है कि समाधान विकल्प के logrotateसाथ copytruncateहै जो इस प्रकार कार्य करता है:

पुरानी लॉग फ़ाइल को स्थानांतरित करने और वैकल्पिक रूप से एक नया बनाने के बजाय, प्रतिलिपि बनाने के बाद मूल लॉग फ़ाइल को अलग करें।

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

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

इस मामले में >>इसके बजाय का उपयोग करना >बेहतर है, भले ही लक्ष्य फ़ाइल अभी बनाई जानी है।


प्रदर्शन

जैसा कि हम देख सकते हैं, दोनों ऑपरेटर न केवल शुरू होने पर बल्कि बाद में भी अलग-अलग कार्य करते हैं। यह कुछ (सूक्ष्म?) प्रदर्शन अंतर का कारण हो सकता है। अभी के लिए मेरे पास इसका समर्थन या खंडन करने के लिए कोई सार्थक परीक्षा परिणाम नहीं है, लेकिन मुझे लगता है कि आपको अपने प्रदर्शन को सामान्य रूप से समान नहीं मानना ​​चाहिए।


9
इसलिए >>अनिवार्य रूप से "हमेशा फ़ाइल के अंत की तलाश करें" जबकि >अंतिम लिखित स्थान पर एक संकेतक रखता है। लगता है कि वहाँ इस तरह वे के रूप में अच्छी तरह से काम में कुछ सूक्ष्म प्रदर्शन अंतर ... हो सकता है
Mokubai

10
सिस्टम कॉल स्तर पर, ध्वज का>> उपयोग करता O_APPENDहैopen() । और वास्तव में, >का उपयोग करता है O_TRUNC, जबकि >>नहीं करता है। का संयोजन O_TRUNC | O_APPENDभी संभव होगा, शेल भाषा बस वह सुविधा प्रदान नहीं करती है।
इलकाचू

3
@jjmontes, मानक स्रोत POSIX होगा: pubs.opengroup.org/onlinepubs/9699919799.2018edition/utilities/… लेकिन निश्चित रूप से बैश के मैनुअल में रीडायरेक्ट ऑपरेटर्स पर विवरण भी हैं, जिनमें गैर-मानक वाले भी शामिल हैं: gnu.org/ सॉफ्टवेयर / बैश / मैनुअल / html_node / रीडायरेक्शन.
html

2
@ilkkachu मुझे यह रुचिकर लगा, क्योंकि यह O_APPEND के बारे में विवरण बताता है जिसके बारे में मैं आपकी टिप्पणी के बाद सोच रहा था :): stackoverflow.com/questions/1154446/…
jjmontes

1
@ मोकूबाई, किसी भी सॅन OS के खुले होने पर फ़ाइल की लंबाई होगी, और एक झंडे की जाँच करना और ऑफ़िस को अंत तक ले जाना अन्य सभी बहीखाता में गायब होना चाहिए। प्रत्येक के पहले O_APPENDएक के साथ अनुकरण करने की कोशिश हालांकि अलग होगी, अतिरिक्त सिस्टम कॉल ओवरहेड होगा। (और निश्चित रूप से यह काम नहीं करेगा, क्योंकि बीच में एक और प्रक्रिया हो सकती है।)lseek()write()write()
ilkachachu
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.