बशर्ते आपने वर्तमान निर्देशिका पर अनुमतियाँ निष्पादित की हों - या उस निर्देशिका पर जहाँ से आपने अपनी शेल स्क्रिप्ट निष्पादित की है - यदि आप एक निर्देशिका के लिए एक संपूर्ण मार्ग चाहते हैं तो आपको इसकी आवश्यकता है cd।
चरण 10 की cdकल्पना
यदि -Pविकल्प प्रभावी होता है, तो $PWDपर्यावरण चर उस स्ट्रिंग पर सेट किया जाएगा जो आउटपुट से होगा pwd -P। यदि नई निर्देशिका, या उस निर्देशिका के किसी भी अभिभावक पर, वर्तमान कार्य निर्देशिका को निर्धारित करने के लिए अपर्याप्त अनुमति है, तो $PWDपर्यावरण चर का मान अनिर्दिष्ट है।
और इसपर pwd -P
मानक आउटपुट के लिए लिखे गए पथनाम में कोई भी घटक नहीं होगा जो प्रकार के प्रतीकात्मक लिंक की फाइलों को संदर्भित करता है। यदि ऐसे कई पथनाम हैं जो pwdउपयोगिता मानक आउटपुट में लिख सकते हैं, एक एकल / स्लैश चरित्र के साथ एक शुरुआत और दो या स्लैश वर्णों के साथ एक या अधिक शुरुआत, तो यह एक एकल / स्लैश चरित्र के साथ आरंभनाम लिखेगा। पाथनाम में प्रमुख या दो / स्लेश वर्णों के बाद कोई अनावश्यक / स्लेश वर्ण नहीं होंगे।
ऐसा इसलिए cd -Pहै क्योंकि वर्तमान वर्किंग डायरेक्टरी को सेट pwd -Pकरना है कि अन्यथा क्या प्रिंट होना चाहिए और यह cd -है $OLDPWDकि निम्नलिखित कामों को प्रिंट करना है:
mkdir ./dir
ln -s ./dir ./ln
cd ./ln ; cd . ; cd -
आउटपुट
/home/mikeserv/test/ln
इसके लिए प्रतीक्षा कीजिए...
cd -P . ; cd . ; cd -
आउटपुट
/home/mikeserv/test/dir
और जब मैं प्रिंट कर cd -रहा हूं तो मैं प्रिंट कर रहा हूं $OLDPWD। cdसेट $PWDही मुझे के रूप में cd -P . $PWDअब के लिए एक निरपेक्ष पथ है /तो मैं किसी भी अन्य चर जरूरत नहीं है -। और वास्तव में, मुझे अनुगामी की भी आवश्यकता नहीं होनी चाहिए, .लेकिन जब कोई अनवांटेड नहीं है, तो एक इंटरैक्टिव शेल में रीसेट $PWDकरने का एक निर्दिष्ट व्यवहार है। इसलिए इसे विकसित करना एक अच्छी आदत है।$HOMEcd
तो बस पथ पर उपरोक्त कार्य करने के लिए पथ ${0%/*}को सत्यापित करने के लिए पर्याप्त से अधिक होना चाहिए $0, लेकिन उस मामले में जो $0स्वयं एक नरम-लिंक है, आप संभवतः इसमें निर्देशिका नहीं बदल सकते हैं, दुर्भाग्य से।
यहाँ एक फ़ंक्शन है जो संभाल लेगा:
zpath() { cd -P . || return
_out() { printf "%s$_zdlm\n" "$PWD/${1##*/}"; }
_cd() { cd -P "$1" ; } >/dev/null 2>&1
while [ $# -gt 0 ] && _cd .
do if _cd "$1"
then _out
elif ! [ -L "$1" ] && [ -e "$1" ]
then _cd "${1%/*}"; _out "$1"
elif [ -L "$1" ]
then ( while set -- "${1%?/}"; _cd "${1%/*}"; [ -L "${1##*/}" ]
do set " $1" "$(_cd -; ls -nd -- "$1"; echo /)"
set -- "${2#*"$1" -> }"
done; _out "$1"
); else ( PS4=ERR:\ NO_SUCH_PATH; set -x; : "$1" )
fi; _cd -; shift; done
unset -f _out _cd; unset -v _zdlm
}
यह वर्तमान शेल में उतना ही करने का प्रयास करता है - एक सब-इनवॉइस को लागू किए बिना - हालांकि त्रुटियों और सॉफ्ट लिंक के लिए सब-इनक्लूड किए गए हैं जो निर्देशिकाओं को इंगित नहीं करते हैं। यह POSIX- संगत शेल और POSIX- संगत के lsसाथ-साथ एक साफ _function()नाम स्थान पर निर्भर करता है । यह अभी भी उत्तरार्द्ध के बिना ठीक काम करेगा, हालांकि यह unsetउस मामले में कुछ वर्तमान शेल फ़ंक्शन को अधिलेखित कर सकता है । सामान्य तौर पर इन सभी निर्भरताओं को यूनिक्स मशीन पर काफी भरोसेमंद रूप से उपलब्ध होना चाहिए।
पहली बात के साथ या बिना बहस के इसे $PWDअपने विहित मूल्य पर रीसेट कर दिया जाता है - यह आवश्यक होने पर अपने लक्ष्य के लिए किसी भी लिंक को हल करता है। तर्कों के बिना बुलाया और इसके बारे में है; लेकिन उनके साथ कहा जाता है और यह हल करेगा और प्रत्येक के लिए पथ को कैनोनिज़लाइज़ करेगा और एक संदेश को प्रिंट करेगा stderrकि क्यों नहीं।
क्योंकि यह ज्यादातर वर्तमान शेल में संचालित होता है इसलिए इसे किसी भी लम्बाई की तर्क सूची को संभालने में सक्षम होना चाहिए। यह $_zdlmचर के लिए भी दिखता है (जो कि यह unsetतब भी होता है जब यह थ्रू होता है) और इसके सी-एस्केप मूल्य को तुरंत अपने प्रत्येक तर्क के दाईं ओर प्रिंट करता है, जिनमें से प्रत्येक को हमेशा एक एकल \nपंक्ति वर्ण द्वारा भी अनुसरण किया जाता है ।
यह बहुत सारी निर्देशिका को बदल देता है, लेकिन, इसे अपने विहित मूल्य पर सेट करने के अलावा, यह प्रभावित नहीं करता है $PWD, हालांकि $OLDPWDकिसी भी माध्यम से इसे तब तक नहीं गिना जा सकता है जब यह माध्यम से हो।
यह जितनी जल्दी हो सके अपने प्रत्येक तर्क को छोड़ने की कोशिश करता है। यह करने के लिए पहले की कोशिश करता cdमें $1। यदि यह तर्क के कैनोनिकल पथ को प्रिंट करता है stdout। यदि यह $1मौजूद नहीं है तो यह जांच सकता है कि यह सॉफ्ट लिंक नहीं है। अगर सच है, तो यह प्रिंट करता है।
इस तरह यह किसी भी फ़ाइल प्रकार तर्क को संभालता है जिसे शेल को संबोधित करने की अनुमति है जब तक $1कि एक प्रतीकात्मक लिंक न हो जो किसी निर्देशिका को इंगित नहीं करता है। उस स्थिति में यह whileएक सबशेल में लूप कहलाता है ।
यह lsलिंक को पढ़ने के लिए कहता है। वर्तमान निर्देशिका को इसके प्रारंभिक मूल्य में परिवर्तित किया जाना चाहिए ताकि किसी भी संदर्भ पथ को मज़बूती से संभाल सकें और इसलिए, कमांड प्रतिस्थापन में फ़ंक्शन करता है।
cd -...ls...echo /
यह lsलिंक के नाम और स्ट्रिंग को पूरी तरह से समाहित करने के लिए इसके आउटपुट के बाईं ओर से स्ट्रिप्स होता है ->। जबकि मैंने पहली बार ऐसा करने से बचने की कोशिश की थी shiftऔर $IFSयह पता चला कि यह सबसे विश्वसनीय तरीका है, जितना मैं समझ सकता हूं। यह वही बात है जो गिल्स के खराब_मानस_रेडलिंक करता है - और यह अच्छी तरह से किया जाता है।
यह इस प्रक्रिया को एक लूप में दोहराएगा जब तक कि फ़ाइल नाम वापस lsनहीं आएगा निश्चित रूप से एक नरम लिंक नहीं है। उस समय यह उस मार्ग को पहले की तरह cdप्रिंट कर देता है।
उदाहरण का उपयोग:
zpath \
/tmp/script \ #symlink to $HOME/test/dir/script.sh
ln \ #symlink to ./dir/
ln/nl \ #symlink to ../..
/dev/fd/0 \ #currently a here-document like : dash <<\HD
/dev/fd/1 \ #(zlink) | dash
file \ #regular file
doesntexist \ #doesnt exist
/dev/disk/by-path/pci-0000:00:16.2-usb-0:3:1.0-scsi-0:0:0:0 \
/dev/./././././././null \
. ..
आउटपुट
/home/mikeserv/test/dir/script.sh
/home/mikeserv/test/dir/
/home/mikeserv/test/
/tmp/zshtpKRVx (deleted)
/proc/17420/fd/pipe:[1782312]
/home/mikeserv/test/file
ERR: NO_SUCH_PATH: doesntexist
/dev/sdd
/dev/null
/home/mikeserv/test/
/home/mikeserv/
या संभवतः ...
ls
dir/ file file? folder/ link@ ln@ script* script3@ script4@
zdlm=\\0 zpath * | cat -A
आउटपुट
/home/mikeserv/test/dir/^@$
/home/mikeserv/test/file^@$
/home/mikeserv/test/file$
^@$
/home/mikeserv/test/folder/^@$
/home/mikeserv/test/file$ #'link' -> 'file\n'
^@$
/home/mikeserv/test/dir/^@$ #'ln' -> './dir'
/home/mikeserv/test/script^@$
/home/mikeserv/test/dir/script.sh^@$ #'script3' -> './dir/script.sh'
/home/mikeserv/test/dir/script.sh^@$ #'script4' -> '/tmp/script' -> ...