जवाबों:
$ स्पर्श ./c $ 'a \ n12 \ tb' फू $ डुह * 0 ए 12 बी 0 फू ल कुल ०
जैसा कि आप देख सकते हैं, -cफ़ाइल को एक विकल्प के रूप में लिया गया था duऔर रिपोर्ट नहीं किया गया है (और आप इसकी totalवजह से लाइन देखते हैं du -c)। इसके अलावा, नामक फ़ाइल a\n12\tbहमें यह सोचने पर मजबूर कर रही है कि क्या फ़ाइलें हैं aऔर कहा जाता है b।
$ du -hs -- *
0 a
12 b
0 -c
0 foo
वह बेहतर है। कम से कम इस समय -cको एक विकल्प के रूप में नहीं लिया जाता है।
$ du -hs ./*
0 ./a
12 b
0 ./-c
0 ./foo
वह तो उससे भी बढ़िया है। ./उपसर्ग रोकता -cसे एक विकल्प और के अभाव के रूप में लिया जा रहा ./से पहले bमें उत्पादन इंगित करता कोई है कि वहाँ bवहाँ में फ़ाइल है, लेकिन वहाँ एक नई पंक्ति चरित्र के साथ एक फ़ाइल है (लेकिन नीचे देखें 1 उस पर आगे digressions के लिए)।
./यदि संभव हो तो उपसर्ग का उपयोग करना अच्छा है, और यदि नहीं और मनमाना डेटा के लिए, आपको हमेशा उपयोग करना चाहिए :
cmd -- "$var"
या:
cmd -- $patterns
यदि विकल्पों के अंत को चिह्नित करने का cmdसमर्थन नहीं करता है --, तो आपको इसे अपने लेखक को बग के रूप में रिपोर्ट करना चाहिए (जब यह पसंद से और इसके लिए प्रलेखित हो तो छोड़कर echo)।
ऐसे मामले हैं जहां ./*समस्याओं का समाधान --नहीं होता है। उदाहरण के लिए:
awk -f file.awk -- *
विफल रहता है अगर वहाँ एक फ़ाइल कहा जाता है a=b.txtवर्तमान निर्देशिका में (awk चर सेट aकरने के लिए b.txtफ़ाइल पर कार्रवाई करने के लिए इसे कह के बजाय)।
awk -f file.awk ./*
समस्या नहीं है क्योंकि ./aएक मान्य awk चर नाम ./a=b.txtनहीं है , इसलिए एक चर असाइनमेंट के रूप में नहीं लिया जाता है।
cat -- * | wc -l
यदि कोई फ़ाइल -वर्तमान निर्देशिका में कॉल की जाती है, तो विफल हो जाती है , क्योंकि यह catउसके स्टड से पढ़ने के लिए कहती है ( -ज्यादातर टेक्स्ट प्रोसेसिंग उपयोगिताओं और cd/ pushd) के लिए विशेष है।
cat ./* | wc -l
ठीक है क्योंकि ./-विशेष नहीं है cat।
इस तरह की चीजें:
grep -l -- foo *.txt | wc -l
उन फ़ाइलों की संख्या को गिनने के लिए जिनमें fooगलत हैं क्योंकि यह मानती है कि फ़ाइल नाम में न्यूलाइन वर्ण नहीं हैं (नई फ़ाइल wc -lवर्ण, grepप्रत्येक फ़ाइल के लिए उन आउटपुट और फ़ाइल नाम में उन लोगों को गिना जाता है )। आपको इसके बजाय उपयोग करना चाहिए:
grep -l foo ./*.txt | grep -c /
( /वर्णों की संख्या गिनना अधिक विश्वसनीय है क्योंकि प्रति फ़ाइलनाम केवल एक ही हो सकता है)।
पुनरावर्ती के लिए grep, समान चाल का उपयोग करना है:
grep -rl foo .//. | grep -c //
./* हालांकि कुछ अवांछित दुष्प्रभाव हो सकते हैं।
cat ./*
प्रति फ़ाइल दो और चरित्र जोड़ता है, जिससे आप तर्कों के अधिकतम आकार + परिवेश तक जल्द ही पहुँच सकते हैं। और कभी-कभी आप नहीं चाहते कि ./आउटपुट में रिपोर्ट किया जाए। पसंद:
grep foo ./*
उत्पादन होगा:
./a.txt: foobar
के बजाय:
a.txt: foobar
1 है । मुझे ऐसा लगता है कि टिप्पणियों में चर्चा के बाद मुझे उस पर यहाँ विस्तार करना होगा।
$ du -hs ./*
0 ./a
12 b
0 ./-c
0 ./foo
ऊपर, कि ./प्रत्येक फ़ाइल की शुरुआत को चिह्नित करने का मतलब है कि हम स्पष्ट रूप से यह पहचान सकते हैं कि प्रत्येक फ़ाइल नाम कहां से शुरू होता है (पर ./) और कहां समाप्त होता है ( ./आउटपुट के अगले या अंत से पहले नई पंक्ति में )।
इसका मतलब यह है कि (के du ./*विपरीत, के उत्पादन du -- *) मज़बूती से पार्स किया जा सकता है, यद्यपि यह आसानी से एक स्क्रिप्ट में नहीं है।
जब आउटपुट एक टर्मिनल पर जाता है, तो बहुत सारे तरीके हैं जो फ़ाइल नाम आपको बेवकूफ बना सकते हैं:
\rकर्सर को लाइन की शुरुआत में \bले जाता है, कर्सर को पीछे ले जाता है, \e[Cआगे (अधिकांश टर्मिनलों में) ...यूनिकोड वर्ण हैं जो ज्यादातर फोंट में स्लैश के समान हैं
$ printf '\u002f \u2044 \u2215 \u2571 \u29F8\n'
/ ⁄ ∕ ╱ ⧸
(देखें कि यह आपके ब्राउज़र में कैसे जाता है)।
एक उदाहरण:
$ touch x 'x ' $'y\bx' $'x\n0\t.\u2215x' $'y\r0\t.\e[Cx'
$ ln x y
$ du -hs ./*
0 ./x
0 ./x
0 ./x
0 .∕x
0 ./x
0 ./x
बहुत सारे हैं, xलेकिन yगायब है।
GNULs जैसे कुछ उपकरण गैर-मुद्रण योग्य वर्णों को एक प्रश्न चिह्न (ध्यान दें कि ∕(U + 2215) प्रिंट करने योग्य है) के स्थान पर बदल देंगे, जब टर्मिनल पर आउटपुट जाता है। जीएनयू duनहीं करता है।
उन्हें स्वयं प्रकट करने के तरीके हैं:
$ ls
x x x?0?.∕x y y?0?.?[Cx y?x
$ LC_ALL=C ls
x x?0?.???x x y y?x y?0?.?[Cx
कैसे देखें ∕में बदल गया ???के बाद हमें बताया lsहै कि हमारे चरित्र सेट ASCII था।
$ du -hs ./* | LC_ALL=C sed -n l
0\t./x$
0\t./x $
0\t./x$
0\t.\342\210\225x$
0\t./y\r0\t.\033[Cx$
0\t./y\bx$
$रेखा के अंत को चिह्नित करता है, इसलिए हम "x"बनाम को स्पॉट कर सकते हैं "x ", सभी गैर-मुद्रण योग्य वर्ण और गैर-एएससीआईआई अक्षर एक बैकस्लैश अनुक्रम द्वारा दर्शाए जाते हैं (बैकस्लैश खुद को दो बैकस्लैश के साथ दर्शाया जाएगा) जिसका अर्थ है कि यह अस्पष्ट है। यह GNU था sed, यह सभी POSIX अनुरूप sedकार्यान्वयनों में समान होना चाहिए लेकिन ध्यान दें कि कुछ पुराने sedकार्यान्वयन लगभग सहायक नहीं हैं।
$ du -hs ./* | cat -vte
0^I./x$
0^I./x $
0^I./x$
0^I.M-bM-^HM-^Ux$
(मानक नहीं बल्कि बहुत सामान्य, cat -Aकुछ कार्यान्वयन के साथ भी )। यह एक सहायक है और एक अलग प्रतिनिधित्व का उपयोग करता है लेकिन अस्पष्ट है ( "^I"और <TAB>उदाहरण के लिए इसे प्रदर्शित किया जाता है)।
$ du -hs ./* | od -vtc
0000000 0 \t . / x \n 0 \t . / x \n 0 \t .
0000020 / x \n 0 \t . 342 210 225 x \n 0 \t . / y
0000040 \r 0 \t . 033 [ C x \n 0 \t . / y \b x
0000060 \n
0000061
यह एक मानक और असंदिग्ध है (और कार्यान्वयन से कार्यान्वयन के अनुरूप) लेकिन पढ़ने में आसान नहीं है।
आप देखेंगे कि yऊपर कभी नहीं दिखा। यही कारण है कि पूरी तरह से असंबद्ध है मुद्दा साथ du -hs *कि फ़ाइल नाम के साथ कोई संबंध नहीं है लेकिन ध्यान दिया जाना चाहिए: क्योंकि duरिपोर्ट डिस्क उपयोग, यह (पहले से ही सूचीबद्ध एक फ़ाइल सब नहीं करने के लिए अन्य लिंक रिपोर्ट नहीं करता duकार्यान्वयन कि तरह व्यवहार करते हैं, हालांकि जब हार्ड लिंक सूचीबद्ध हैं कमांड लाइन पर)।
[a-z0-9.+-] ।
/tmpया बहुत महंगी कारों के साथ एक क्षेत्र $HOME) और यह एक प्रश्नोत्तर साइट पर जाने के लिए और भी बदतर है और कहें कि आपकी कार को बिना किसी स्थिति के निर्दिष्ट किए बिना लॉक करना ठीक है (लॉक गैरेज, स्क्रिप्ट में) आपने अपने आप से केवल एक मशीन पर चलाया है जो किसी नेटवर्क या रिमूवेबल स्टोरेज से कनेक्ट नहीं है ...)
"b "या "a\bb") एक टर्मिनल पर एक उपयोगकर्ता को बेवकूफ बनाएगा, लेकिन इसके उत्पादन को पार्स करने वाली स्क्रिप्ट नहीं du ./*। मुझे शायद उसके बारे में एक नोट जोड़ना चाहिए। कल करेंगे। ध्यान दें कि पहले मुझे सामान्य अर्थों में विशेषाधिकार प्राप्त थे, न कि root(हालांकि rootपाठ्यक्रम के सभी अधिक लागू होते हैं )। newlines की अनुमति है, उन्हें अनदेखा करना एक बग है। कीड़े को शोषण की आदत है। आपको केस के आधार पर जोखिम को मापने के लिए मिला है। अच्छा कोडिंग अभ्यास कई मामलों में समस्याओं से बच सकता है। निश्चित रूप से एसई पर, हमें जागरूकता बढ़ानी चाहिए।
वहाँ एक के बीच कोई अंतर है *और ./*क्या या तो इच्छा सूची फ़ाइलें के संदर्भ में। दूसरा अंतर केवल 2 फॉर्म के साथ होगा, प्रत्येक फाइल ./में उनके सामने एक डॉट स्लैश होगा, जो आमतौर पर वर्तमान निर्देशिका का मतलब है।
याद रखें कि .निर्देशिका वर्तमान निर्देशिका के लिए एक आशुलिपि संकेतन है।
$ ls -la | head -4
total 28864
drwx------. 104 saml saml 12288 Jan 23 20:04 .
drwxr-xr-x. 4 root root 4096 Jul 8 2013 ..
-rw-rw-r--. 1 saml saml 972 Oct 6 20:26 abcdefg
आप खुद को समझा सकते हैं कि इन 2 सूचियों को अनिवार्य रूप से एक ही बात है echoकि यह देखने के लिए कि शेल उन्हें क्या विस्तार देगा।
$ echo *
$ echo ./*
ये 2 कमांड आपकी वर्तमान निर्देशिका की सभी फाइलों को सूचीबद्ध करेगी।
हम कुछ नकली डेटा बना सकते हैं जैसे:
$ touch file{1..5}
$ ll
total 0
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file1
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file2
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file3
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file4
-rw-rw-r--. 1 saml saml 0 Jan 24 07:14 file5
अब जब हम उपरोक्त echoकमांड का उपयोग करते हैं तो हमें निम्न आउटपुट दिखाई देते हैं:
$ echo *
file1 file2 file3 file4 file5
$ echo ./*
./file1 ./file2 ./file3 ./file4 ./file5
यह अंतर अनावश्यक लग सकता है, लेकिन ऐसी परिस्थितियां हैं, जहां आप विभिन्न यूनिक्स कमांड लाइन टूल्स की गारंटी देना चाहते हैं, जिन्हें आप कमांड लाइन के माध्यम से उनके लिए फाइलनाम पास कर रहे हैं, और अधिक कुछ नहीं!
जैसा कि @ स्टीफन का जवाब बताता है कि यूनिक्स में फाइलों और निर्देशिकाओं के नामकरण के दौरान कौन से वर्ण कानूनी हैं, खतरनाक फाइलनामों का निर्माण किया जा सकता है, जो अप्रत्याशित दुष्प्रभाव होते हैं जब वे कमांड लाइन पर विभिन्न यूनिक्स कमांडों को पास करते हैं।
इसलिए अक्सर उपयोग का उपयोग ./गारंटी देने में मदद करने के लिए किया जाएगा कि विस्तारित फ़ाइलनाम को फ़ाइल नाम के रूप में माना जाता है जब विभिन्न यूनिक्स आदेशों के तर्क के रूप में पारित किया जाता है।