मैं थोड़ा हैरान हूं कि किसी ने अभी तक इसका उल्लेख नहीं किया है, लेकिन आप 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/dir
ARG
.
.
PATH
ARGA
/path/to/my/bin/dir
.
PATH
/path/to/my/bin/dir
PATH
शायद अधिक महत्वपूर्ण बात यह है कि 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 में निर्दिष्ट नहीं है, इसलिए मैक ओएस, सोलारिस और अन्य गैर-लिनक्स यूनिक्स में इसकी उपलब्धता संदिग्ध है। (वास्तव में, मैं सिर्फ एक टिप्पणी पढ़ता हूं जो कहती है "readlink
readlink
readlink -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
}