बैश स्टार * वाइल्डकार्ड हमेशा एक (आरोही) सॉर्ट की गई सूची का उत्पादन करता है?


53

मेरे पास फाइलों से भरी एक निर्देशिका है जैसे logXXकि XX जहां एक दो-चरित्र है, शून्य-गद्देदार, अपरकेस हेक्स जैसे:

log00
log01
log02
...
log0A
log0B
log0C
...
log4E
log4F
log50
...

आम तौर पर कुल 20 या 30 फाइलें कहने से कम होगी। मेरे विशेष सिस्टम पर तारीख और समय कुछ ऐसा नहीं है जिस पर भरोसा किया जा सकता है (कोई विश्वसनीय एनटीपी या जीपीएस समय स्रोतों के साथ एक एम्बेडेड सिस्टम)। हालाँकि, जैसा कि ऊपर दिखाया गया है, फ़ाइल नाम मज़बूती से बढ़ेंगे।

मैं grepएक निश्चित प्रकार के सबसे हाल ही में लॉग प्रविष्टि के लिए सभी फाइलों के माध्यम से करना चाहता हूं , मैं catएक साथ फ़ाइलों की उम्मीद कर रहा था जैसे ...

cat /tmp/logs/log* | grep 'WARNING 07 -' | tail -n1

हालांकि यह मेरे लिए की है कि विभिन्न संस्करणों हुआ bashया shया zshआदि कैसे के बारे में अलग विचार है हो सकता है *विस्तार होता है।

man bashपेज कहना नहीं है या नहीं, के विस्तार *मिलान फ़ाइल नाम का एक निश्चित रूप से आरोही वर्णानुक्रम सूची होगी। यह हर बार आरोही प्रतीत होता है, मैंने इसे उन सभी प्रणालियों पर आज़माया है जो मेरे पास उपलब्ध हैं - लेकिन क्या यह निश्चित व्यवहार है या केवल कार्यान्वयन विशिष्ट है?

दूसरे शब्दों में, क्या मैं cat /tmp/logs/log*वर्णमाला के क्रम में अपनी सभी लॉग फ़ाइलों को एक साथ जोड़ने के लिए बिल्कुल भरोसा कर सकता हूं ?


1
@ADDB शेल के लिए डिफ़ॉल्ट सॉर्ट क्रम sortउसी के समान है जब यह फ़ाइल नाम ग्लोबिंग पैटर्न का विस्तार कर रहा है।
Kusalananda

9
यह भयानक फ़ाइल नामकरण अभ्यास है। आप लॉग (0) के साथ अपना रन क्यों शुरू करते हैं = - infty?
ईपी

14
@EP हमारा फाइल सिस्टम एक जटिल 7 आयामी हाइपर-टॉरॉइड है जिसमें इनोड्स की असली संख्या होती है। यह व्यस्त
बॉक्स की

1
आप बच सकते हैं catके साथ grep -h pattern /tmp/logs/log*मैच के लिए फ़ाइल नाम prepending को दबाने के लिए। (कम से कम GNU grep के साथ, मैंने POSIX या बिजीबॉक्स की जांच नहीं की।)
पीटर कॉर्ड्स

1
@ कुसलानंद आपने बेकार उपयोग के बारे में सुना है cat, यह बेकार हैsort
बिल्ली

जवाबों:


52

सभी गोले में, ग्लोब को डिफ़ॉल्ट रूप से क्रमबद्ध किया जाता है। वे पहले से ही/etc/glob 70 के दशक के शुरुआती दिनों में यूनिक्स के पहले संस्करण में ग्लब्स का विस्तार करने के लिए केन थॉम्पसन के शेल द्वारा बुलाए गए सहायक थे (और जिसने ग्लब्स को उनका नाम दिया)।

shPOSIX के लिए , उन्हें strcoll()उस तरीके से सॉर्ट करने की आवश्यकता होती है , जो उपयोगकर्ता के लोकेल में सॉर्टिंग ऑर्डर का उपयोग कर रहा है, जैसे lsकि कुछ अभी भी इसके माध्यम से करते हैं strcmp(), जो केवल बाइट मानों पर आधारित है।

$ dash -c 'echo *'
Log01B log-0D log00 log01 log02 log0A log0B log0C log4E log4F log50 log log lóg01
$ bash -c 'echo *'
log log log00 log01 lóg01 Log01B log02 log0A log0B log0C log-0D log4E log4F log50
$ zsh -c 'echo *'
log log log00 log01 lóg01 Log01B log02 log0A log0B log0C log-0D log4E log4F log50
$ ls
log  log  log00  log01  lóg01  Log01B  log02  log0A  log0B  log0C  log-0D  log4E  log4F  log50
$ ls | sort
log
log
log00
log01
lóg01
Log01B
log02
log0A
log0B
log0C
log-0D
log4E
log4F
log50

आप ऊपर उन नोटिसों के लिए देख सकते हैं जो लोकेल के आधार पर छँटाई करते हैं, यहाँ एक en_GB.UTF-8लोकल के साथ GNU सिस्टम पर , -फ़ाइल नामों में छँटाई के लिए अनदेखा किया जाता है (अधिकांश विराम चिह्न वर्ण)। óएक और अधिक की उम्मीद जिस तरह से (कम से कम ब्रिटिश लोगों के लिए) में क्रमबद्ध हो जाता है, और मामले को नजरअंदाज कर दिया जाता है (जब यह संबंधों तय करने के लिए आता है को छोड़कर)।

हालाँकि, आप log you'll log inc के लिए कुछ विसंगतियों पर ध्यान देंगे। ऐसा इसलिए है क्योंकि GNU स्थानों में That's और the का छँटाई क्रम परिभाषित नहीं है (वर्तमान में, उम्मीद है कि यह किसी दिन तय हो जाएगा)। वे एक ही क्रमबद्ध करते हैं, इसलिए आपको यादृच्छिक परिणाम मिलते हैं।

स्थान बदलने से छँटाई क्रम प्रभावित होगा। आप एक समान strcmp()सॉर्ट पाने के लिए लोकेल को C पर सेट कर सकते हैं :

$ bash -c 'echo *'
log log log00 log01 lóg01 Log01B log02 log0.2 log0A log0B log0C log-0D log4E log4F log50
$ bash -c 'LC_ALL=C; echo *'
Log01B log-0D log0.2 log00 log01 log02 log0A log0B log0C log4E log4F log50 log log lóg01

ध्यान दें कि कुछ स्थान सभी-एएससीआईआई ऑल-अलनम स्ट्रिंग्स के लिए भी कुछ भ्रम पैदा कर सकते हैं। चेक वालों की तरह (जीएनयू सिस्टम पर कम से कम) chएक कोलेटिंग तत्व है जो इसके बाद होता है h:

$ LC_ALL=cs_CZ.UTF-8 bash -c 'echo *'
log0Ah log0Bh log0Dh log0Ch

या, जैसा कि @ninjalj द्वारा बताया गया है, यहां तक ​​कि हंगेरियन स्थानों में भी अजीब बातें हैं:

$ LC_ALL=hu_HU.UTF-8 bash -c 'echo *'
logX LOGx LOGX logZ LOGz LOGZ logY LOGY LOGy

में zsh, आप ग्लोब क्वालिफायर के साथ छँटाई चुन सकते हैं । उदाहरण के लिए:

echo *(om) # to sort by modification time
echo *(oL) # to sort by size
echo *(On) # for a *reverse* sort by name
echo *(o+myfunction) # sort using a user-defined function
echo *(N)  # to NOT sort
echo *(n)  # sort by name, but numerically, and so on.

सांख्यिक प्रकार को echo *(n)भी numericglobsortविकल्प के साथ विश्व स्तर पर सक्षम किया जा सकता है:

$ zsh -c 'echo *'
log log log00 log01 lóg01 Log01B log02 log0.2 log0A log0B log0C log-0D log4E log4F log50
$ zsh -o numericglobsort -c 'echo *'
log log log00 lóg01 Log01B log0.2 log0A log0B log0C log01 log02 log-0D log4E log4F log50

यदि आप (जैसा कि मैं था) उस आदेश में उस विशेष उदाहरण (मेरे ब्रिटिश लोकेल का उपयोग करके) को भ्रमित कर रहे हैं, तो विवरण के लिए यहां देखें।


1
'Ch' केस भी अजीब हो सकता है: कुछ लोकेशन यह तय कर सकती हैं कि 'ch', 'Ch' और 'CH' प्रत्येक 1 कोलेटिंग एलिमेंट हैं, जबकि 'cH' दो कोलिंग तत्व हैं। देखें: unicode.org/cldr/trac/ticket/889 करंट CLDR पूरी तरह से सुसंगत नहीं लगता है: current हंगेरी ( unicode.org/cldr/trac/browser/trunk/common/collation-hu.xml ) में नियम हैं &C<cs<<<Cs<<<CS, जबकि &C<cs<<<cS<<<Cs<<<CSएक प्रस्तावित प्रायोगिक मसौदे के रूप में चिह्नित है। सीएलडीआर में आयात किए गए कुछ पुराने डेटा से देखते हुए, पुराने एआईएक्स और एमएस को "लोअरकेस तो अपरकेस दो अलग-अलग कोलाजेशन तत्व" दृश्य पसंद करते थे।
नवजलज

और मैंने ऐसे सिस्टम देखे हैं जहाँ यह वैसे भी काम नहीं करता था। :(
जोशुआ

38

बैश के लिए आदमी पृष्ठ निर्दिष्ट करता है:

पथनाम विस्तार

शब्द बंटवारे के बाद, जब तक -fविकल्प सेट किया गया है, बैश पात्रों के लिए प्रत्येक शब्द को स्कैन करता है *, ?और [। यदि इनमें से कोई एक अक्षर दिखाई देता है, तो शब्द को एक पैटर्न के रूप में माना जाता है, और पैटर्न से मेल खाने वाले फ़ाइलनामों की वर्णानुक्रम में क्रमबद्ध सूची के साथ प्रतिस्थापित किया जाता है […]।


1
बस पोटीन या manपाठ के प्रतिपादन में एक दिलचस्प बग पाया ... अगर मैं जिस पाठ को खोज रहा हूं उसे "शब्द लिपटे हुए" मिलता है, तो / a खोज आदेश नहीं मिलेगा। बस मेरे टर्मिनल को अधिकतम किया और वहाँ यह है :)
Wossname

2
आपने कवर किया bash। थो ओपी को "zsh आदि" में भी रुचि थी
Kusalananda

29

जब तक आप कुछ गोले में कुछ बहुत विशिष्ट शेल विकल्पों को ट्रिगर नहीं करते हैं, आउटपुट समान होने की गारंटी है।

आदेश POSIX मानक में निर्दिष्ट है :

यदि पैटर्न किसी भी मौजूदा फ़ाइल नाम या पथनाम से मेल खाता है, तो पैटर्न को उन फ़ाइल नाम और मार्गनाम से बदल दिया जाएगा, जो वर्तमान लोकेल में प्रभावी क्रम के अनुसार क्रमबद्ध हैं । यदि इस कोलाज़िंग अनुक्रम में सभी वर्णों का कुल क्रम नहीं है (XBD LC_COLLATE देखें), किसी भी फ़ाइल नाम या समान रूप से समान रूप से टकराए जाने वाले मार्ग का नाम POSIX लोकेल के लिए कोलाटिंग अनुक्रम का उपयोग करते हुए बाइट-बाइट की तुलना में आगे होना चाहिए।

POSIX लोकेल में LC_COLLATE श्रेणी भी देखें , जो संक्षेप में कहती है कि यदि LC_COLLATE=C, तो ASIIII क्रम में चीजें आर्डर की जाती हैं।


bashमैनुअल का उल्लेख है

LC_COLLATE

यह वैरिएबल pathname विस्तार के परिणामों को सॉर्ट करते समय उपयोग किए जाने वाले कॉलेरेशन ऑर्डर को निर्धारित करता है, और pathname विस्तार और पैटर्न मिलान के भीतर रेंज एक्सप्रेशन, समतुल्यता वर्ग, और कोलाटिंग अनुक्रम के व्यवहार को निर्धारित करता है।

ksh93और zshइसी तरह का शब्दांकन है, जो मुझे विश्वास दिलाता है कि वे इस संबंध में POSIX मानक का पालन करते हैं।

अन्य गोले, जैसे फिल्नाम ग्लोबिंग के परिणामस्वरूप होने वाले फ़ाइलनामों की छंटाई के बारे में कुछ नहीं कहते हैं pdkshऔर dashन ही कहते हैं। मुझे विश्वास है कि यह मतलब है कि वे अभी भी एक ही मानक का पालन करते हैं, कम से कम जब POSIX लोकेल का उपयोग कर रहा हूँ। मेरे अनुभव में, मैं एक ऐसे शेल के पार नहीं आया हूं जो एएससीआईआई फ़ाइलनामों के किसी भी "अजीब" प्रकार को ओवरटेक करता है।


2
उस numericglobsortविकल्प को देखें जो zshछँटाई को प्रभावित करेगा। हालाँकि मैं इसके बजाय इसे echo *(n)विश्व स्तर पर विकल्प की तरह प्रति-ग्लोब के आधार पर सक्षम करूँगा ।
स्टीफन चेजेलस

एक निपिक। डिफ़ॉल्ट मोड में बैश, पॉज़िक्स-अनुरूप नहीं है।
fpmurphy

@ fpmurphy1 और कहें
Kusalananda

@Kusalananda। बैश को कभी भी पोसिक्स-शिकायत के रूप में प्रमाणित नहीं किया गया है। बैश में "POSIX- अनुपालन" प्राप्त करने के लिए, आपको --posixकमांड लाइन विकल्प के साथ बैश को लागू करना होगा या निष्पादित करना होगाset -o posix
fpmurphy

@ fpmurphy1 हां, लेकिन फ़ाइल नाम ग्लोबिंग वर्णों के विस्तार की छंटनी बैश के posixमोड से प्रभावित नहीं होती है । Gnu.org/software/bash/manual/html_node/Bash-POSIX-Mode.html देखें इससे मुझे विश्वास होता है (आशा है, बल्कि) कि सॉर्टिंग POSIX अनुरूप है।
Kusalananda

1

यदि प्राथमिक लक्ष्य उनकी उम्र के अनुसार इनपुट फ़ाइलों को क्रमबद्ध करना है, तो सबसे पहले, आप लिख सकते हैं

(cd /tmp/logs; cat `ls -rt log*`) | grep whatever

और अगर घुमाया और संकुचित लॉग भी शामिल हैं:

(cd /tmp/logs; zcat -f `ls -rt log*`) | grep whatever

4
यह उल्लेख किया गया था कि फाइलों पर टाइमस्टैम्प पर भरोसा नहीं किया जाना था।
कुसलानंद

3
@ कुसलानंद, यह सही है, हमारे सिस्टम का समय आम तौर पर एक यादृच्छिक संख्या जनरेटर माना जाता है :)
Wossname
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.