अगर मुझे tail
25 जीबी टेक्स्टफाइल चाहिए, तो क्या tail
कमांड पूरी फाइल को पढ़ती है?
चूँकि एक फाइल डिस्क पर बिखरी हुई हो सकती है जिसकी मैं कल्पना करता हूँ, लेकिन मुझे इस तरह के इंटर्न को अच्छी तरह से समझ में नहीं आता है।
अगर मुझे tail
25 जीबी टेक्स्टफाइल चाहिए, तो क्या tail
कमांड पूरी फाइल को पढ़ती है?
चूँकि एक फाइल डिस्क पर बिखरी हुई हो सकती है जिसकी मैं कल्पना करता हूँ, लेकिन मुझे इस तरह के इंटर्न को अच्छी तरह से समझ में नहीं आता है।
जवाबों:
नहीं, tail
पूरी फाइल नहीं पढ़ता है, यह अंत तक चाहता है, तब तक ब्लॉक को पीछे की ओर पढ़ें जब तक अपेक्षित संख्या में रेखाएं नहीं पहुंच जाती हैं, तब यह फ़ाइल के अंत तक उचित दिशा में लाइनों को प्रदर्शित करता है, और संभवतया निगरानी की निगरानी करता है यदि -f
विकल्प का उपयोग किया जाता है तो फ़ाइल करें ।
ध्यान दें कि tail
कोई विकल्प नहीं है, लेकिन पूरे डेटा को पढ़ने के लिए यदि कोई गैर शोध योग्य इनपुट प्रदान किया जाता है, उदाहरण के लिए पाइप से पढ़ते समय।
इसी तरह, जब फ़ाइल की शुरुआत से शुरू होने वाली लाइनों को देखने के लिए कहा जाता है, तो जब समर्थन किया जाता है तो tail -n +linenumber
सिंटैक्स या tail +linenumber
गैर मानक विकल्प का उपयोग करते हुए , tail
स्पष्ट रूप से पूरी फ़ाइल (जब तक कि बाधित नहीं होती है) पढ़ता है।
tail +n
पूरी फाइल पढ़ेंगे - पहले वांछित संख्याओं को खोजने के लिए, फिर बाकी आउटपुट के लिए।
tail
कार्यान्वयन इसे ठीक से नहीं करते हैं या नहीं करते हैं। उदाहरण के लिए व्यस्तबॉक्स 1.21.1 tail
उस संबंध में टूट गया है। यह भी ध्यान दें कि व्यवहार तब होता है जब tail
स्टड और जहां स्टड एक नियमित फ़ाइल होती है और फ़ाइल में प्रारंभिक स्थिति शुरू में नहीं होती tail
है जब इसे आमंत्रित किया जाता है (जैसे { cat > /dev/null; tail; } < file
)
आप देख सकते थे कि कैसे tail
अपने आप काम करता है। जैसा कि आप मेरी एक फाइल के read
लिए तीन बार कर सकते हैं और कुल मिलाकर लगभग 10K बाइट्स पढ़े जाते हैं:
strace 2>&1 tail ./huge-file >/dev/null | grep -e "read" -e "lseek" -e "open" -e "close"
open("./huge-file", O_RDONLY) = 3
lseek(3, 0, SEEK_CUR) = 0
lseek(3, 0, SEEK_END) = 80552644
lseek(3, 80551936, SEEK_SET) = 80551936
read(3, ""..., 708) = 708
lseek(3, 80543744, SEEK_SET) = 80543744
read(3, ""..., 8192) = 8192
read(3, ""..., 708) = 708
close(3) = 0
strace
दिखाता है कि सिस्टम कॉल tail
कब चलता है। सिस्टम के बारे में कुछ introdaction कॉल आप यहां पढ़ सकते हैं en.wikipedia.org/wiki/System_call । संक्षेप में - खुला - एक फ़ाइल खोलता है और एक हैंडल देता है (इस उदाहरण में 3), वह lseek
स्थान जहां आप पढ़ने जा रहे हैं और read
सिर्फ पढ़ता है और जैसा कि आप देख सकते हैं कि यह कितने बाइट पढ़ता है,
चूंकि एक डिस्क पर एक फ़ाइल बिखरी हो सकती है, मुझे लगता है कि इसे [क्रमिक रूप से फ़ाइल को पढ़ना है], लेकिन मुझे इस तरह की आंतरिक जानकारी अच्छी तरह से समझ में नहीं आती।
जैसा कि अब आप जानते हैं, tail
बस फाइल के अंत में (सिस्टम कॉल के साथ lseek
), और पीछे की ओर काम करता है। लेकिन ऊपर उद्धृत टिप्पणी में, आप सोच रहे हैं "फ़ाइल के अंत को खोजने के लिए डिस्क पर पूंछ कैसे पता चलता है?"
उत्तर सरल है: पूंछ को पता नहीं है। उपयोगकर्ता-स्तरीय प्रक्रियाएं फ़ाइलों को निरंतर धाराओं के रूप में देखती हैं, इसलिए सभी tail
जान सकते हैं कि फ़ाइल की शुरुआत से ऑफसेट है। लेकिन फाइल सिस्टम में, फाइल का "इनकोड" (डायरेक्टरी एंट्री) फाइल के डेटा ब्लॉक के भौतिक स्थान को दर्शाती संख्याओं की सूची से जुड़ा होता है। जब आप फ़ाइल से पढ़ते हैं, तो कर्नेल / डिवाइस ड्राइवर यह पता लगाता है कि आपको किस भाग की आवश्यकता है, डिस्क पर इसके स्थान को काम करता है और इसे आपके पास लाता है।
इस तरह की चीज़ों के लिए हमारे पास ऑपरेटिंग सिस्टम हैं: इसलिए आपको इस बारे में चिंता करने की ज़रूरत नहीं है कि आपकी फ़ाइल के ब्लॉक कहाँ बिखरे हुए हैं।
यदि पूरी फाइल को पढ़ा head
या tail
प्रतीत होता है, तो एक संभावित कारण यह है कि फ़ाइल में कुछ या कोई नई वर्ण नहीं हैं । मैंने इस पर कुछ महीने पहले एक बहुत बड़ी (गीगाबाइट्स) JSON बूँद के साथ ट्रिप किया था, जिसे बिना किसी व्हाट्सएप के सीरियल किया गया था, स्ट्रिंग्स में भी नहीं।
यदि आपके पास GNU हेड / टेल है तो आप लाइनों के बजाय -c N
पहले / अंतिम N बाइट्स को प्रिंट करने के लिए उपयोग कर सकते हैं , लेकिन दुर्भाग्य से यह POSIX फीचर नहीं है।
जैसा कि आप स्रोत कोड लाइन 525 में देख सकते हैं, आप कार्यान्वयन के लिए टिप्पणियां देख सकते हैं।
/* Print the last N_LINES lines from the end of file FD.
Go backward through the file, reading 'BUFSIZ' bytes at a time (except
probably the first), until we hit the start of the file or have
read NUMBER newlines.
START_POS is the starting position of the read pointer for the file
associated with FD (may be nonzero).
END_POS is the file offset of EOF (one larger than offset of last byte).
Return true if successful. */