बशर्ते आपने वर्तमान निर्देशिका पर अनुमतियाँ निष्पादित की हों - या उस निर्देशिका पर जहाँ से आपने अपनी शेल स्क्रिप्ट निष्पादित की है - यदि आप एक निर्देशिका के लिए एक संपूर्ण मार्ग चाहते हैं तो आपको इसकी आवश्यकता है 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
करने का एक निर्दिष्ट व्यवहार है। इसलिए इसे विकसित करना एक अच्छी आदत है।$HOME
cd
तो बस पथ पर उपरोक्त कार्य करने के लिए पथ ${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' -> ...