क्या पूंछ पूरी फाइल पढ़ती है?


113

अगर मुझे tail25 जीबी टेक्स्टफाइल चाहिए, तो क्या tailकमांड पूरी फाइल को पढ़ती है?

चूँकि एक फाइल डिस्क पर बिखरी हुई हो सकती है जिसकी मैं कल्पना करता हूँ, लेकिन मुझे इस तरह के इंटर्न को अच्छी तरह से समझ में नहीं आता है।

जवाबों:


119

नहीं, tailपूरी फाइल नहीं पढ़ता है, यह अंत तक चाहता है, तब तक ब्लॉक को पीछे की ओर पढ़ें जब तक अपेक्षित संख्या में रेखाएं नहीं पहुंच जाती हैं, तब यह फ़ाइल के अंत तक उचित दिशा में लाइनों को प्रदर्शित करता है, और संभवतया निगरानी की निगरानी करता है यदि -fविकल्प का उपयोग किया जाता है तो फ़ाइल करें ।

ध्यान दें कि tailकोई विकल्प नहीं है, लेकिन पूरे डेटा को पढ़ने के लिए यदि कोई गैर शोध योग्य इनपुट प्रदान किया जाता है, उदाहरण के लिए पाइप से पढ़ते समय।

इसी तरह, जब फ़ाइल की शुरुआत से शुरू होने वाली लाइनों को देखने के लिए कहा जाता है, तो जब समर्थन किया जाता है तो tail -n +linenumberसिंटैक्स या tail +linenumberगैर मानक विकल्प का उपयोग करते हुए , tailस्पष्ट रूप से पूरी फ़ाइल (जब तक कि बाधित नहीं होती है) पढ़ता है।


14
लानत है, बहुत तेज :-)। यहाँ प्रासंगिक स्रोत कोड हैफ़ाइल FD के अंत से अंतिम N_LINES लाइनें प्रिंट करें। फ़ाइल के माध्यम से पीछे जाएं, 'BUFSIZ' बाइट्स को एक बार में पढ़ना (शायद पहले को छोड़कर), जब तक कि हम फ़ाइल की शुरुआत को हिट नहीं करते या NUMBER न्यूलाइन्स नहीं पढ़ते।
पैट्रिक

1
इसके अलावा, tail +nपूरी फाइल पढ़ेंगे - पहले वांछित संख्याओं को खोजने के लिए, फिर बाकी आउटपुट के लिए।
एसएफ।

@SF। वास्तव में, जवाब अद्यतन।
jlliagre

4
ध्यान दें कि सभी tailकार्यान्वयन इसे ठीक से नहीं करते हैं या नहीं करते हैं। उदाहरण के लिए व्यस्तबॉक्स 1.21.1 tailउस संबंध में टूट गया है। यह भी ध्यान दें कि व्यवहार तब होता है जब tailस्टड और जहां स्टड एक नियमित फ़ाइल होती है और फ़ाइल में प्रारंभिक स्थिति शुरू में नहीं होती tailहै जब इसे आमंत्रित किया जाता है (जैसे { cat > /dev/null; tail; } < file)
स्टीफन चेज़लस

4
@StephaneChazelas * निक्स - अजीब किनारे के मामलों की दुनिया सामान्य हो रही है। (हालांकि खोज योग्य बनाम गैर-शोध योग्य इनपुट निश्चित रूप से एक वैध बिंदु है।)
सीवीएन

69

आप देख सकते थे कि कैसे 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

मैं यह नहीं देखता कि यह सवाल का जवाब कैसे देता है। क्या आप बता सकते हैं कि यहाँ क्या हो रहा है?
इयॉन सैमुअल मैकलीन एल्डर

10
straceदिखाता है कि सिस्टम कॉल tailकब चलता है। सिस्टम के बारे में कुछ introdaction कॉल आप यहां पढ़ सकते हैं en.wikipedia.org/wiki/System_call । संक्षेप में - खुला - एक फ़ाइल खोलता है और एक हैंडल देता है (इस उदाहरण में 3), वह lseekस्थान जहां आप पढ़ने जा रहे हैं और readसिर्फ पढ़ता है और जैसा कि आप देख सकते हैं कि यह कितने बाइट पढ़ता है,
सर्गेई कुरेंकोव

2
इसलिए सिस्टम कॉल का विश्लेषण आप कभी-कभी समझ सकते हैं कि एक कार्यक्रम कैसे काम करता है।
सर्गेई कुरेनकोव

26

चूंकि एक डिस्क पर एक फ़ाइल बिखरी हो सकती है, मुझे लगता है कि इसे [क्रमिक रूप से फ़ाइल को पढ़ना है], लेकिन मुझे इस तरह की आंतरिक जानकारी अच्छी तरह से समझ में नहीं आती।

जैसा कि अब आप जानते हैं, tailबस फाइल के अंत में (सिस्टम कॉल के साथ lseek), और पीछे की ओर काम करता है। लेकिन ऊपर उद्धृत टिप्पणी में, आप सोच रहे हैं "फ़ाइल के अंत को खोजने के लिए डिस्क पर पूंछ कैसे पता चलता है?"

उत्तर सरल है: पूंछ को पता नहीं है। उपयोगकर्ता-स्तरीय प्रक्रियाएं फ़ाइलों को निरंतर धाराओं के रूप में देखती हैं, इसलिए सभी tailजान सकते हैं कि फ़ाइल की शुरुआत से ऑफसेट है। लेकिन फाइल सिस्टम में, फाइल का "इनकोड" (डायरेक्टरी एंट्री) फाइल के डेटा ब्लॉक के भौतिक स्थान को दर्शाती संख्याओं की सूची से जुड़ा होता है। जब आप फ़ाइल से पढ़ते हैं, तो कर्नेल / डिवाइस ड्राइवर यह पता लगाता है कि आपको किस भाग की आवश्यकता है, डिस्क पर इसके स्थान को काम करता है और इसे आपके पास लाता है।

इस तरह की चीज़ों के लिए हमारे पास ऑपरेटिंग सिस्टम हैं: इसलिए आपको इस बारे में चिंता करने की ज़रूरत नहीं है कि आपकी फ़ाइल के ब्लॉक कहाँ बिखरे हुए हैं।


2

यदि पूरी फाइल को पढ़ा headया tail प्रतीत होता है, तो एक संभावित कारण यह है कि फ़ाइल में कुछ या कोई नई वर्ण नहीं हैं । मैंने इस पर कुछ महीने पहले एक बहुत बड़ी (गीगाबाइट्स) JSON बूँद के साथ ट्रिप किया था, जिसे बिना किसी व्हाट्सएप के सीरियल किया गया था, स्ट्रिंग्स में भी नहीं।

यदि आपके पास GNU हेड / टेल है तो आप लाइनों के बजाय -c Nपहले / अंतिम N बाइट्स को प्रिंट करने के लिए उपयोग कर सकते हैं , लेकिन दुर्भाग्य से यह POSIX फीचर नहीं है।


1

जैसा कि आप स्रोत कोड लाइन 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.  */
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.