सबसे सामान्य मामलों में, $0
स्क्रिप्ट के लिए एक पथ, निरपेक्ष या सापेक्ष होगा, इसलिए
script_path=$(readlink -e -- "$0")
(यह मानते हुए कि एक readlink
कमांड है और यह समर्थन करता है -e
) आम तौर पर स्क्रिप्ट के लिए कैनोनिकल निरपेक्ष पथ प्राप्त करने का एक अच्छा तरीका है।
$0
इंटरप्रेटर में पास किए गए स्क्रिप्ट को निर्दिष्ट करने वाले तर्क से असाइन किया गया है।
उदाहरण के लिए:
the-shell -shell-options the/script its args
$0
हो जाता है the/script
।
जब आप दौड़ते हैं:
the/script its args
आपका खोल एक करेगा:
exec("the/script", ["the/script", "its", "args"])
यदि स्क्रिप्ट में #! /bin/sh -
उदाहरण के लिए वह धमाकेदार है, तो सिस्टम उसे बदल देगा:
exec("/bin/sh", ["/bin/sh" or "the/script", "-", "the/script", "its", "args"])
(यदि इसमें वह-बैंग शामिल नहीं है, या अधिक आम तौर पर यदि सिस्टम एक ENOEXEC त्रुटि देता है, तो आपका शेल जो कि एक ही काम करेगा)
कुछ सिस्टम पर सेतु / सेटगिड स्क्रिप्ट के लिए एक अपवाद है, जहां सिस्टम स्क्रिप्ट को कुछ पर खोल देगा fd
x
और इसके बजाय चलाएगा:
exec("/bin/sh", ["/bin/sh" or "the/script", "-", "/dev/fd/x", "its", "args"])
दौड़ की स्थिति से बचने के लिए (जिसमें मामला $0
शामिल होगा /dev/fd/x
)।
अब, आप यह तर्क दे सकते हैं कि /dev/fd/x
यह स्क्रिप्ट का एक मार्ग है। ध्यान दें कि यदि आप से पढ़ते हैं $0
, तो आप इनपुट का उपभोग करते हुए स्क्रिप्ट को तोड़ देंगे।
अब, अगर स्क्रिप्ट कमांड नाम को आमंत्रित किया जाता है तो इसमें कोई अंतर नहीं होता है। में:
the-script its args
आपका खोल ऊपर दिखेगा the-script
में $PATH
। $PATH
कुछ निर्देशिकाओं के लिए निरपेक्ष या सापेक्ष (रिक्त स्ट्रिंग सहित) पथ हो सकते हैं। उदाहरण के लिए, यदि वर्तमान निर्देशिका में $PATH
शामिल है /bin:/usr/bin:
और the-script
पाया जाता है, तो शेल एक करेगा:
exec("the-script", ["the-script", "its", "args"])
जो बन जाएगा:
exec("/bin/sh", ["/bin/sh" or "the-script", "-", "the-script", "its", "args"]
या यदि यह पाया जाता है /usr/bin
:
exec("/usr/bin/the-script", ["the-script", "its", "args"])
exec("/bin/sh", ["/bin/sh" or "the-script" or "/usr/bin/the-script",
"-", "/usr/bin/the-script", "its", "args")
उपर्युक्त कोने के मामले को छोड़कर उन सभी मामलों में, $0
स्क्रिप्ट में एक पथ (पूर्ण या सापेक्ष) होगा।
अब, एक स्क्रिप्ट के रूप में भी कहा जा सकता है:
the-interpreter the-script its args
जब the-script
ऊपर से स्लैश वर्ण नहीं होते हैं, तो व्यवहार शेल से शेल में थोड़ा भिन्न होता है।
पुराने एटी एंड टी ksh
कार्यान्वयन वास्तव में स्क्रिप्ट को बिना शर्त के देख रहे थे $PATH
(जो वास्तव में बग और सेतु लिपियों के लिए एक सुरक्षा छेद $0
था ), इसलिए वास्तव में स्क्रिप्ट में एक पथ शामिल नहीं था जब तक कि $PATH
वास्तव the-script
में वर्तमान निर्देशिका में खोजने के लिए लुकअप नहीं हुआ था ।
यदि यह पठनीय है, तो नया AT & T वर्तमान निर्देशिका में ksh
प्रयास और व्याख्या करेगा the-script
। यदि नहीं यह एक पठनीय के लिए देखने हैं और निष्पादन the-script
में $PATH
।
इसके लिए bash
, यह जाँच करता है कि the-script
क्या वर्तमान निर्देशिका में है (और एक टूटी हुई सिमलिंक नहीं है) और यदि नहीं, तो एक पठनीय (आवश्यक रूप से निष्पादन योग्य नहीं) the-script
के लिए खोज $PATH
।
zsh
में sh
अनुकरण की तरह करना होगा bash
, सिवाय इसके कि यदि the-script
वर्तमान निर्देशिका में एक टूट सिमलिंक है, यह एक के लिए खोज नहीं होगा the-script
में $PATH
है और इसके बजाय एक त्रुटि रिपोर्ट करेंगे।
अन्य सभी बॉर्न-जैसे गोले the-script
ऊपर नहीं दिखते $PATH
।
वैसे भी उन सभी गोले के लिए, यदि आप पाते हैं कि $0
इसमें शामिल नहीं है /
और पठनीय नहीं है, तो संभवतः इसे ऊपर देखा गया है $PATH
। फिर, जैसा कि फ़ाइलों के $PATH
निष्पादन योग्य होने की संभावना है, यह संभवतः command -v -- "$0"
अपने पथ को खोजने के लिए उपयोग करने के लिए एक सुरक्षित सन्निकटन है (हालांकि यह काम नहीं करेगा यदि $0
शेल शेल या कीवर्ड (अधिकांश गोले में) का नाम भी हो।
इसलिए यदि आप वास्तव में उस मामले के लिए कवर करना चाहते हैं, तो आप इसे लिख सकते हैं:
progname=$0
[ -r "$progname" ] || progname=$(
IFS=:; set -f
for i in ${PATH-$(getconf PATH)}""; do
case $i in
"") p=$progname;;
*/) p=$i$progname;;
*) p=$i/$progname
esac
[ -r "$p" ] && exec printf '%s\n' "$p"
done
exit 1
) && progname=$(readlink -e -- "$progname") ||
progname=unknown
( ""
संलग्न करने $PATH
के लिए एक अनुगामी खाली तत्व को गोले के साथ संरक्षित करना है, जो विभाजक के बजाय सीमांकक के$IFS
रूप में कार्य करता है )।
अब, एक स्क्रिप्ट को लागू करने के लिए अधिक गूढ़ तरीके हैं। एक कर सकता है:
the-shell < the-script
या:
cat the-script | the-shell
उस मामले में, $0
पहला तर्क होगा ( argv[0]
) कि इंटरप्रेटर प्राप्त हुआ (ऊपर the-shell
, लेकिन वह कुछ भी हो सकता है, हालांकि आम तौर पर या तो आधार या उस दुभाषिया के लिए एक रास्ता)।
यह पता लगाना कि आप उस स्थिति में हैं, जिसके आधार पर मूल्य $0
विश्वसनीय नहीं है। आप ps -o args= -p "$$"
एक सुराग पाने के लिए आउटपुट को देख सकते हैं। पाइप के मामले में, कोई वास्तविक तरीका नहीं है जिससे आप स्क्रिप्ट पर वापस जा सकते हैं।
एक भी कर सकता है:
the-shell -c '. the-script' blah blih
फिर, zsh
(और बॉर्न शेल के कुछ पुराने कार्यान्वयन को छोड़कर ), $0
होगा blah
। फिर, उन गोले में स्क्रिप्ट के रास्ते पर आना मुश्किल है।
या:
the-shell -c "$(cat the-script)" blah blih
आदि।
यह सुनिश्चित करने के लिए कि आपके पास अधिकार है $progname
, आप इसमें एक विशिष्ट स्ट्रिंग की खोज कर सकते हैं:
progname=$0
[ -r "$progname" ] || progname=$(
IFS=:; set -f
for i in ${PATH-$(getconf PATH)}:; do
case $i in
"") p=$progname;;
*/) p=$i$progname;;
*) p=$i/$progname
esac
[ -r "$p" ] && exec printf '%s\n' "$p"
done
exit 1
) && progname=$(readlink -e -- "$progname") ||
progname=unknown
[ -f "$progname" ] && grep -q 7YQLVVD3UIUDTA32LSE8U9UOHH < "$progname" ||
progname=unknown
लेकिन फिर से मुझे नहीं लगता कि यह प्रयास के लायक है।
$0
स्क्रिप्ट के अलावा कुछ और है, जो प्रश्न शीर्षक का जवाब देता है। हालांकि, मैं उन स्थितियों में भी दिलचस्पी रखता हूं जहां$0
स्क्रिप्ट ही है, लेकिन निर्देशिका शामिल नहीं है। विशेष रूप से, मैं SO उत्तर पर की गई टिप्पणी को समझने की कोशिश कर रहा हूं।