मैं थोड़ा हैरान हूं कि किसी ने अभी तक इसका उल्लेख नहीं किया है, लेकिन आप readlink -fसापेक्ष पथों को निरपेक्ष पथों में बदलने के लिए उपयोग कर सकते हैं , और उन्हें इस तरह से पाथ में जोड़ सकते हैं।
उदाहरण के लिए, गिलौम पेरौल्ट-आर्कबॉल्ट के जवाब में सुधार करने के लिए,
pathappend() {
for ARG in "$@"
do
if [ -d "$ARG" ] && [[ ":$PATH:" != *":$ARG:"* ]]; then
PATH="${PATH:+"$PATH:"}$ARG"
fi
done
}
हो जाता है
pathappend() {
for ARG in "$@"
do
if [ -d "$ARG" ] && [[ ":$PATH:" != *":$ARG:"* ]]
then
if ARGA=$(readlink -f "$ARG") #notice me
then
if [ -d "$ARGA" ] && [[ ":$PATH:" != *":$ARGA:"* ]]
then
PATH="${PATH:+"$PATH:"}$ARGA"
fi
else
PATH="${PATH:+"$PATH:"}$ARG"
fi
fi
done
}
1. मूल बातें - यह क्या अच्छा है?
readlink -fआदेश (अन्य बातों के अलावा) एक निरपेक्ष पथ के लिए एक रिश्तेदार पथ परिवर्तित कर देंगे। इससे आप कुछ ऐसा कर सकते हैं
$ cd / path / to / my / bin / dir
$ पाथपेंड ।
$ गूंज "$ पाथ"
<your_old_path> : / path / to / my / bin / dir
2. हम दो बार पाथे होने के लिए परीक्षा क्यों देते हैं?
खैर, उपरोक्त उदाहरण पर विचार करें। यदि उपयोगकर्ता निर्देशिका
से दूसरी बार कहता है , तो
होगा । बेशक, इसमें उपस्थित नहीं होंगे । लेकिन फिर
( पहले से ही पूर्ण पथ के बराबर ) पर सेट किया जाएगा , जो पहले से ही अंदर है । इसलिए हमें दूसरी बार जोड़ने से बचने की आवश्यकता है ।pathappend ./path/to/my/bin/dirARG..PATHARGA/path/to/my/bin/dir.PATH/path/to/my/bin/dirPATH
शायद अधिक महत्वपूर्ण बात यह है कि readlinkजैसा कि इसके नाम का अर्थ है, एक प्रतीकात्मक लिंक को देखना और इसमें शामिल होने वाले पथनाम को पढ़ना (जैसे, अंक)। उदाहरण के लिए:
$ ls -ld /usr/lib/perl/5.14
-rwxrwxrwx 1 root root Sep 3 2015 /usr/lib/perl/5.14 -> 5.14.2
$ readlink /usr/lib/perl/5.14
5.14.2
$ readlink -f /usr/lib/perl/5.14
/usr/lib/perl/5.14.2
अब, यदि आप कहते हैं pathappend /usr/lib/perl/5.14, और आप पहले से ही /usr/lib/perl/5.14अपने पेट में हैं, ठीक है, यह ठीक है; हम इसे वैसे ही छोड़ सकते हैं जैसे यह है। लेकिन, अगर /usr/lib/perl/5.14आपके पथ में पहले से ही नहीं है, हम कहते हैं readlinkऔर मिल ARGA= /usr/lib/perl/5.14.2, और फिर हम जोड़ने कि करने के लिए PATH। लेकिन एक मिनट प्रतीक्षा करें - यदि आपने पहले ही कहा था pathappend /usr/lib/perl/5.14, तो आपके पास पहले से ही /usr/lib/perl/5.14.2आपके पेट में है, और, फिर से, हमें इसे PATHदूसरी बार जोड़ने से बचने के लिए जांचना होगा ।
3. डील क्या है if ARGA=$(readlink -f "$ARG")?
यदि यह अस्पष्ट है, तो यह रेखा परीक्षण करती है कि क्या readlinkसफल होता है। यह सिर्फ अच्छा, रक्षात्मक प्रोग्रामिंग अभ्यास है। यदि हम कमांड n से आउटपुट मी का उपयोग कमांड n (जहाँ m < n ) के भाग के
रूप में करने जा रहे हैं , तो यह जाँचना समझदारी है कि क्या कमांड m विफल हुआ है और किसी तरह से इसे संभालता है। मुझे नहीं लगता कि यह संभव है कि विफल होगा - लेकिन, जैसा कि ओएस एक्स
और अन्य जगहों से एक मनमाना फ़ाइल के पूर्ण पथ को पुनः प्राप्त करने के लिए चर्चा की गई है, एक GNU आविष्कार है। यह POSIX में निर्दिष्ट नहीं है, इसलिए मैक ओएस, सोलारिस और अन्य गैर-लिनक्स यूनिक्स में इसकी उपलब्धता संदिग्ध है। (वास्तव में, मैं सिर्फ एक टिप्पणी पढ़ता हूं जो कहती है "readlinkreadlinkreadlink -fमैक ओएस एक्स 10.11.6 पर काम करने के लिए प्रतीत नहीं होता है, लेकिन realpathबॉक्स से बाहर काम करता है। ”तो, यदि आप एक ऐसी प्रणाली पर हैं readlink, जो आपके पास नहीं है , या जहां readlink -fकाम नहीं करता है, तो आप इसे संशोधित करने में सक्षम हो सकते हैं। स्क्रिप्ट का उपयोग करें realpath।) एक सुरक्षा जाल स्थापित करके, हम अपने कोड को कुछ अधिक पोर्टेबल बनाते हैं।
बेशक, यदि आप एक ऐसी प्रणाली पर हैं जिसमें readlink(या realpath) नहीं है , तो आप नहीं करना चाहते हैं ।pathappend .
दूसरा -dपरीक्षण ( [ -d "$ARGA" ]) वास्तव में शायद अनावश्यक है। मैं किसी भी परिदृश्य के बारे में नहीं सोच सकता जहाँ $ARGएक निर्देशिका है और readlinkसफल है, लेकिन $ARGAएक निर्देशिका नहीं है। मैंने ifतीसरे कथन को बनाने के लिए पहले कथन को कॉपी-पेस्ट किया और मैंने -dआलस से वहाँ से परीक्षा छोड़ दी ।
4. कोई अन्य टिप्पणियाँ?
हाँ। यहां कई अन्य उत्तरों की तरह, यह एक परीक्षण करता है कि क्या प्रत्येक तर्क एक निर्देशिका है, अगर यह है तो इसे संसाधित करता है, और इसे अनदेखा करता है यदि यह नहीं है। यह (या नहीं हो सकता) यदि आप उपयोग कर रहे हैं पर्याप्त हो सकता है pathappend
"में केवल ." (जैसे फ़ाइलों .bash_profileऔर .bashrc) और अन्य लिपियों। लेकिन, जैसा कि इस उत्तर में दिखाया गया है (ऊपर), यह अंतःक्रियात्मक रूप से उपयोग करने के लिए पूरी तरह से संभव है। अगर आप ऐसा करेंगे तो आप बहुत हैरान होंगे
$ pathappend /usr/local/nysql/bin
$ mysql
-bash: mysql: command not found
आप नोटिस किया कि मैंने कहा कि nysql
में pathappendआदेश के बजाय mysql? और pathappendइसने कुछ नहीं कहा; यह सिर्फ चुपचाप गलत तर्क को नजरअंदाज कर दिया?
जैसा कि मैंने ऊपर कहा, त्रुटियों को संभालने के लिए यह अच्छा अभ्यास है। यहाँ एक उदाहरण है:
pathappend() {
for ARG in "$@"
do
if [ -d "$ARG" ]
then
if [[ ":$PATH:" != *":$ARG:"* ]]
then
if ARGA=$(readlink -f "$ARG") #notice me
then
if [[ ":$PATH:" != *":$ARGA:"* ]]
then
PATH="${PATH:+"$PATH:"}$ARGA"
fi
else
PATH="${PATH:+"$PATH:"}$ARG"
fi
fi
else
printf "Error: %s is not a directory.\n" "$ARG" >&2
fi
done
}