जवाबों:
$ स्पर्श ./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
गायब है।
GNU
Ls जैसे कुछ उपकरण गैर-मुद्रण योग्य वर्णों को एक प्रश्न चिह्न (ध्यान दें कि ∕
(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
यह अंतर अनावश्यक लग सकता है, लेकिन ऐसी परिस्थितियां हैं, जहां आप विभिन्न यूनिक्स कमांड लाइन टूल्स की गारंटी देना चाहते हैं, जिन्हें आप कमांड लाइन के माध्यम से उनके लिए फाइलनाम पास कर रहे हैं, और अधिक कुछ नहीं!
जैसा कि @ स्टीफन का जवाब बताता है कि यूनिक्स में फाइलों और निर्देशिकाओं के नामकरण के दौरान कौन से वर्ण कानूनी हैं, खतरनाक फाइलनामों का निर्माण किया जा सकता है, जो अप्रत्याशित दुष्प्रभाव होते हैं जब वे कमांड लाइन पर विभिन्न यूनिक्स कमांडों को पास करते हैं।
इसलिए अक्सर उपयोग का उपयोग ./
गारंटी देने में मदद करने के लिए किया जाएगा कि विस्तारित फ़ाइलनाम को फ़ाइल नाम के रूप में माना जाता है जब विभिन्न यूनिक्स आदेशों के तर्क के रूप में पारित किया जाता है।