मैं एक निर्देशिका ट्री में सबसे पुरानी फ़ाइल खोजने के लिए शेल वन-लाइनर की तलाश कर रहा हूं।
मैं एक निर्देशिका ट्री में सबसे पुरानी फ़ाइल खोजने के लिए शेल वन-लाइनर की तलाश कर रहा हूं।
जवाबों:
यह काम करता है (डैनियल एंडरसन के सुझाव को शामिल करने के लिए अद्यतन):
find -type f -printf '%T+ %p\n' | sort | head -n 1
findतथ्य से खाली है क्योंकि मेरे पास फ़ाइल नाम नई लाइन है।
यह थोड़ा अधिक पोर्टेबल है और क्योंकि यह GNU findएक्सटेंशन पर निर्भर नहीं है -printf, इसलिए यह BSD / OS X पर भी काम करता है:
find . -type f -print0 | xargs -0 ls -ltr | head -n 1
यहाँ केवल नकारात्मक पक्ष यह है कि यह कुछ हद तक सीमित है ARG_MAX(जो कि सबसे नए गुठली के लिए अप्रासंगिक होना चाहिए )। इसलिए, यदि getconf ARG_MAXमेरे सिस्टम में 262,144 से अधिक वर्ण वापस आ गए हैं, तो यह आपको सही परिणाम नहीं देता है। यह भी POSIX- अनुरूप नहीं है क्योंकि -print0और xargs -0नहीं है।
इस समस्या के कुछ और समाधान यहाँ दिए गए हैं: मैं एक निर्देशिका में नवीनतम (सबसे नई, सबसे पुरानी, सबसे पुरानी) फ़ाइल कैसे ढूँढ सकता हूँ? - ग्रेग का विकी
xargs: ls: terminated by signal 13साइड इफेक्ट के रूप में एक त्रुटि का उत्सर्जन करता है। मैं अनुमान लगा रहा हूं कि यह SIGPIPE है। मुझे नहीं पता कि जब मैं अपने समाधान में सिर को आउटपुट करता हूं तो मुझे एक समान त्रुटि क्यों नहीं मिलती है।
headकमांड है जो एक बार लाइन को पढ़ने के बाद क्विट करता है और इस तरह पाइप को "ब्रेक" करता है, मुझे लगता है। आपको त्रुटि नहीं मिलती है क्योंकि sortइसके बारे में शिकायत नहीं लगती है, लेकिन lsदूसरे मामले में करता है।
xargsआह्वान करने की आवश्यकता है ls। उस स्थिति में, उन एकाधिक चालानों के क्रमबद्ध आउटपुट समाप्त हो जाते हैं जब उन्हें विलय किया जाना चाहिए।
lsउसे नहीं देख सकते हैं और सबसे पुरानी फाइल को देख सकते हैं, आपका समाधान संभवतः कमांड लाइन की लंबाई सीमा को पार कर जाएगा , जिससे lsकई बार आह्वान किया जा सकता है। आपको गलत उत्तर मिल जाएगा, लेकिन आप कभी नहीं जान पाएंगे।
निम्न आदेशों को किसी भी तरह के अजीब फ़ाइल नामों के साथ काम करने की गारंटी है:
find -type f -printf "%T+ %p\0" | sort -z | grep -zom 1 ".*" | cat
find -type f -printf "%T@ %T+ %p\0" | \
sort -nz | grep -zom 1 ".*" | sed 's/[^ ]* //'
stat -c "%y %n" "$(find -type f -printf "%T@ %p\0" | \
sort -nz | grep -zom 1 ".*" | sed 's/[^ ]* //')"
\0एक लाइनफीड कैरेक्टर ( ) के बजाय एक अशक्त बाइट ( ) का उपयोग करना \nसुनिश्चित करता है कि फाइल के नामों में से एक लाइनफीड कैरेक्टर के मामले में खोज का आउटपुट अभी भी समझ में आएगा।
-zस्विच दोनों तरह और ग्रेप अंत लाइन पात्रों के रूप में केवल अशक्त बाइट्स की व्याख्या करता है। चूंकि सिर के लिए ऐसा कोई स्विच नहीं है, हम grep -m 1इसके बजाय (केवल एक घटना) का उपयोग करते हैं।
आदेशों का निष्पादन समय (मेरी मशीन पर मापा गया) द्वारा किया जाता है।
पहला कमांड सबसे धीमा होगा क्योंकि इसमें हर फाइल के माइम को पहले मानव पठनीय प्रारूप में बदलना होगा और फिर उन स्ट्रिंग्स को क्रमबद्ध करना होगा। बिल्ली के लिए पाइपिंग उत्पादन को रंग देने से बचा जाता है।
दूसरा कमांड थोड़ा तेज है। हालांकि यह अभी भी दिनांक रूपांतरण करता है, संख्यात्मक रूप से छांटना ( sort -n) उन सेकंडों को समाप्त कर देता है जब से यूनिक्स युग थोड़ा तेज होता है। यूनिक्स के युग के बाद सेड सेकंड को हटा देता है।
अंतिम कमांड बिल्कुल भी रूपांतरण नहीं करता है और पहले दो की तुलना में काफी तेज होना चाहिए। खोज आदेश स्वयं सबसे पुरानी फ़ाइल के माइम को प्रदर्शित नहीं करेगा, इसलिए स्टेट की आवश्यकता है।
यद्यपि स्वीकृत उत्तर और यहां अन्य लोग काम करते हैं, यदि आपके पास एक बहुत बड़ा पेड़ है, तो वे सभी फाइलों के पूरे गुच्छा को सॉर्ट करेंगे।
बेहतर यह होगा कि हम उन्हें सूचीबद्ध कर सकें और सबसे पुराने को ट्रैक कर सकें, बिना किसी क्रम के।
यही कारण है कि मैं इस वैकल्पिक समाधान के साथ आया:
ls -lRU $PWD/* | awk 'BEGIN {cont=0; oldd=strftime("%Y%m%d"); } { gsub(/-/,"",$6); if (substr($1,0,1)=="/") { pat=substr($1,0,length($0)-1)"/"; }; if( $6 != "") {if ( $6 < oldd ) { oldd=$6; oldf=pat$8; }; print $6, pat$8; count++;}} END { print "Oldest date: ", oldd, "\nFile:", oldf, "\nTotal compared: ", count}'
मुझे उम्मीद है कि यह किसी भी मदद का हो सकता है, भले ही सवाल थोड़ा पुराना हो।
संपादित 1: यह परिवर्तन रिक्त स्थान के साथ फ़ाइलों और निर्देशिकाओं को पार्स करने की अनुमति देता है। यह तेजी से जड़ में जारी करने /और अब तक की सबसे पुरानी फ़ाइल खोजने के लिए पर्याप्त है ।
ls -lRU --time-style=long-iso "$PWD"/* | awk 'BEGIN {cont=0; oldd=strftime("%Y%m%d"); } { gsub(/-/,"",$6); if (substr($0,0,1)=="/") { pat=substr($0,0,length($0)-1)"/"; $6="" }; if( $6 ~ /^[0-9]+$/) {if ( $6 < oldd ) { oldd=$6; oldf=$8; for(i=9; i<=NF; i++) oldf=oldf $i; oldf=pat oldf; }; count++;}} END { print "Oldest date: ", oldd, "\nFile:", oldf, "\nTotal compared: ", count}'
कमांड समझाया:
इसे चलाना:
~ $ time ls -lRU "$ PWD" / * | जाग आदि।
सबसे पुरानी तारीख: 19691231
फाइल: /home/../../backupold/.../EXAMPLES/how-to-program.txt
कुल तुलना: 111438
वास्तविक 0m1.135s
उपयोगकर्ता 0m0.872s
sys 0m0.760s
संपादित करें 2: एक ही अवधारणा है, बेहतर समाधान का उपयोग findको देखने के लिए उपयोग समय (का उपयोग %Tपहले से printfके लिए संशोधन समय या %Cके लिए स्थिति परिवर्तन के बजाय)।
find . -wholename "*" -type f -printf "%AY%Am%Ad %h/%f\n" | awk 'BEGIN {cont=0; oldd=strftime("%Y%m%d"); } { if ($1 < oldd) { oldd=$1; oldf=$2; for(i=3; i<=NF; i++) oldf=oldf " " $i; }; count++; } END { print "Oldest date: ", oldd, "\nFile:", oldf, "\nTotal compared: ", count}'
EDIT 3: कमांड बलो संशोधन समय का उपयोग करता है और वृद्धिशील प्रगति को भी प्रिंट करता है क्योंकि यह पुरानी और पुरानी फाइलों को ढूंढता है, जो तब उपयोगी होता है जब आपके पास कुछ गलत टाइमस्टैम्प्स (जैसे 1970-01-01):
find . -wholename "*" -type f -printf "%TY%Tm%Td %h/%f\n" | awk 'BEGIN {cont=0; oldd=strftime("%Y%m%d"); } { if ($1 < oldd) { oldd=$1; oldf=$2; for(i=3; i<=NF; i++) oldf=oldf " " $i; print oldd " " oldf; }; count++; } END { print "Oldest date: ", oldd, "\nFile:", oldf, "\nTotal compared: ", count}'
lsस्क्रिप्टिंग के लिए बुरा है क्योंकि इसका आउटपुट मशीनों के लिए नहीं है, आउटपुट स्वरूपण पूरे कार्यान्वयन में भिन्न होता है। जैसा कि आपने पहले ही बताया findहै कि यह स्क्रिप्टिंग के लिए अच्छा है, लेकिन lsसमाधान के बारे में बताने से पहले उस जानकारी को जोड़ना भी अच्छा हो सकता है ।
कृपया ls का उपयोग करें - मैन पेज आपको बताता है कि डायरेक्टरी को कैसे ऑर्डर करना है।
ls -clt | head -n 2
-N 2 है, इसलिए आपको आउटपुट में "कुल" नहीं मिलता है। यदि आप केवल फ़ाइल का नाम चाहते हैं।
ls -t | head -n 1
और अगर आपको सामान्य क्रम में सूची की आवश्यकता है (नवीनतम फ़ाइल प्राप्त करना)
ls -tr | head -n 1
खोजने के लिए उपयोग करने की तुलना में बहुत आसान है, बहुत तेज है, और अधिक मजबूत है - फ़ाइल नामकरण स्वरूपों के बारे में चिंता करने की ज़रूरत नहीं है। यह लगभग सभी प्रणालियों पर भी काम करना चाहिए।
find ! -type d -printf "%T@ %p\n" | sort -n | head -n1
sort -n।
ऐसा लगता है कि "सबसे पुराने" द्वारा अधिकांश लोगों ने माना है कि आपका मतलब "सबसे पुराना संशोधन समय" था। शायद "सबसे पुराना" की सबसे सख्त व्याख्या के अनुसार, इसे सही किया गया है, लेकिन यदि आप सबसे पुराने पहुंच समय के साथ चाहते हैं , तो मैं सबसे अच्छा उत्तर इस प्रकार संशोधित करूंगा:
find -type f -printf '%A+ %p\n' | sort | head -n 1
ध्यान दें %A+।
set $(find /search/dirname -type f -printf '%T+ %h/%f\n' | sort | head -n 1) && echo $2
find ./search/dirname -type f -printf '%T+ %h/%f\n' दो स्तंभों में दिनांक और फ़ाइल नाम प्रिंट करता है।sort | head -n1 सबसे पुरानी फ़ाइल के अनुरूप लाइन रखता है।echo $2 दूसरा कॉलम, यानी फ़ाइल नाम प्रदर्शित करता है।
find -type f -printf '%T+ %p\n' | sort | head -1