2009-09-08 4 views
32

/bin/bash के साथ, मैं कैसे पता लगाऊंगा कि उपयोगकर्ता के पास $ PATH चर में एक विशिष्ट निर्देशिका है या नहीं?पता लगाएं कि उपयोगकर्ता के पथ में एक विशिष्ट निर्देशिका है

उदाहरण के लिए

if [ -p "$HOME/bin" ]; then 
    echo "Your path is missing ~/bin, you might want to add it." 
else 
    echo "Your path is correctly set" 
fi 

उत्तर

3

कुछ सच में सरल और अनुभवहीन:

echo "$PATH"|grep -q whatever && echo "found it" 

कहाँ जो कुछ भी है कि आप क्या खोज रहे हैं। && के बजाय आप $? को एक चर में डाल सकते हैं या उचित if कथन का उपयोग कर सकते हैं।

प्रतिबंधों में शामिल हैं:

  • ऊपर इस तथ्य के बावजूद बड़े रास्तों में से सबस्ट्रिंग ("बिन" पर मिलान कोशिश करते हैं और यह शायद यह मिलेगा मिलान करता है, कि "बिन" अपने रास्ते में नहीं है,/बिन और/usr/bin कर रहे हैं)
  • ऊपर स्वचालित रूप से की तरह शॉर्टकट का विस्तार नहीं होगा ~

या एक पर्ल एक लाइनर का उपयोग कर:

perl -e 'exit(!(grep(m{^/usr/bin$},split(":", $ENV{PATH}))) > 0)' && echo "found it" 

अभी भी यह सीमा है कि यह किसी भी शैल विस्तार नहीं करेगा, लेकिन यदि कोई सबस्ट्रिंग मेल खाता है तो यह असफल नहीं होता है। (उपरोक्त मैचों "/usr/bin", अगर यह स्पष्ट नहीं था)।

+1

जेसनवॉफ के उत्तर में लाइन और कॉलन की शुरुआत/समाप्ति से मेल खाने से आपकी सबस्ट्रिंग मैच सीमा का ख्याल रखा जाता है। Tilde विस्तार एक आम मुद्दा नहीं है, क्योंकि ज्यादातर लोग इसे असाइन किए जाने पर विस्तारित करने की अनुमति देते हैं (उदा। 'PATH = "~/bin: $ पथ" ') यदि आवश्यक हो तो प्रतिस्थापन के साथ देखभाल की जा सकती है। – Cascabel

+2

अच्छा, किसी ने 3.5 साल बाद इसे घटा दिया। और एक टिप्पणी नहीं छोड़ी। लंगड़ा। –

+0

मैं gons समाधान को colons के साथ पैटर्न लपेटने का उपयोग कर रहा हूँ। – elias

102

grep का उपयोग करना अधिक है, और अगर आप आरई मेटाएक्टैक्टर्स को शामिल करने के लिए कुछ भी खोज रहे हैं तो परेशानी हो सकती है। यह समस्या बैश के builtin [[ कमांड के साथ पूरी तरह से अच्छी तरह से हल किया जा सकता:

if [[ ":$PATH:" == *":$HOME/bin:"* ]]; then 
    echo "Your path is correctly set" 
else 
    echo "Your path is missing ~/bin, you might want to add it." 
fi 

ध्यान दें कि इससे पहले कि दोनों $ पथ के विस्तार और पथ के लिए खोज करने के लिए कोलन जोड़ने सबस्ट्रिंग मिलान मुद्दा हल करती है; पथ को दोहराते हुए मेटाएक्टएक्टर्स के साथ परेशानी से बचा जाता है।

+4

यदि '$ HOME/bin'' $ PATH' की शुरुआत या अंत में है, तो प्रत्येक छोर पर एक कोलन होने की संभावना नहीं है। –

+8

मुझे यकीन नहीं है कि मैं आपकी आपत्ति को समझ रहा हूं। उदाहरण के लिए, यदि $ PATH है/usr/bin:/bin:/usr/sbin:/sbin:/home/fred/bin, फिर ":/usr/bin:/bin:/usr/sbin:/sbin:/घर/फ्रेड/बिन: "मिलान होगा *":/home/fred/bin: "* बस ठीक है। –

+6

आप सही हैं। मैं "$ पाथ" के आसपास के कोलों की भूमिका को देखने में विफल रहा था। माफ़ कीजिये। –

10

यहाँ कैसे grep बिना यह करना है:

if [[ $PATH == ?(*:)$HOME/bin?(:*) ]] 

कुंजी यहां कोलन बनाने के लिए है और ?() निर्माण का उपयोग कर वैकल्पिक वाइल्डकार्ड। इस फ़ॉर्म में अक्षरों से परे के साथ किसी भी समस्या नहीं होनी चाहिए, लेकिन अगर आप उद्धरण शामिल करना चाहते हैं यह कि उन्हें कहां जाना है:

if [[ "$PATH" == ?(*:)"$HOME/bin"?(:*) ]] 

यह एक और तरीका यह करने के लिए मैच ऑपरेटर (=~) तो सिंटैक्स का उपयोग है अधिक की तरह grep की है:

if [[ "$PATH" =~ (^|:)"${HOME}/bin"(:|$) ]] 
+0

'? (: *)' एक [विस्तारित ग्लोब] (https://mywiki.wooledge.org/glob#extglob) पैटर्न है जिसे अधिकांश प्लेटफार्मों ('shopt -s extglob') पर अलग से स्पष्ट रूप से सक्षम करने की आवश्यकता है। – tripleee

0

$PATH: द्वारा अलग तार कि निर्देशिका की एक सूची का वर्णन की एक सूची है। एक निर्देशिका / से अलग तारों की एक सूची है। दो अलग-अलग तार एक ही निर्देशिका को इंगित कर सकते हैं (जैसे $HOME और ~, या /usr/local/bin और /usr/local/bin/)। इसलिए हमें उन नियमों को ठीक करना होगा जिन्हें हम तुलना करना/जांचना चाहते हैं। मैं पूरे तारों की तुलना/जांच करने का सुझाव देता हूं, न कि भौतिक निर्देशिकाएं, लेकिन डुप्लिकेट हटाएं और / पीछे पीछे हटाना।

पहले उसे हटा डुप्लिकेट और $PATH से / अनुगामी:

 
echo $PATH | tr -s/| sed 's/\/:/:/g;s/:/\n/g' 

अब मान लीजिए $d निर्देशिका आप जाँच करना चाहते हैं। फिर $PATH में $d जांचने के लिए पिछली कमांड पाइप करें।

 
echo $PATH | tr -s/| sed 's/\/:/:/g;s/:/\n/g' | grep -q "^$d$" || echo "missing $d" 
0

मैं अगर एक निर्देशिका वर्तमान PATH में सूचीबद्ध है रिपोर्ट करने के लिए निम्नलिखित खोल समारोह लिखा था। यह फ़ंक्शन POSIX- संगत है और डैश और बैश जैसे संगत शैल में चलाएगा (बैश-विशिष्ट विशेषताओं पर भरोसा किए बिना)।

इसमें एक सापेक्ष पथ को एक पूर्ण पथ में परिवर्तित करने की कार्यक्षमता शामिल है। यह readlink या realpath उपयोगिताओं का उपयोग करता है लेकिन यदि आपूर्ति निर्देशिका में .. या उसके पथ के घटक के रूप में अन्य लिंक नहीं हैं तो इन उपकरणों की आवश्यकता नहीं है। इसके अलावा, फ़ंक्शन को शैल के बाहर के किसी भी प्रोग्राम की आवश्यकता नहीं होती है।

# Check that the specified directory exists – and is in the PATH. 
is_dir_in_path() 
{ 
    if [ -z "${1:-}" ]; then 
    printf "The path to a directory must be provided as an argument.\n" >&2 
    return 1 
    fi 

    # Check that the specified path is a directory that exists. 
    if ! [ -d "$1" ]; then 
    printf "Error: ‘%s’ is not a directory.\n" "$1" >&2 
    return 1 
    fi 

    # Use absolute path for the directory if a relative path was specified. 
    if command -v readlink >/dev/null ; then 
    dir="$(readlink -f "$1")" 
    elif command -v realpath >/dev/null ; then 
    dir="$(realpath "$1")" 
    else 
    case "$1" in 
     /*) 
     # The path of the provided directory is already absolute. 
     dir="$1" 
     ;; 
     *) 
     # Prepend the path of the current directory. 
     dir="$PWD/$1" 
     ;; 
    esac 
    printf "Warning: neither ‘readlink’ nor ‘realpath’ are available.\n" 
    printf "Ensure that the specified directory does not contain ‘..’ in its path.\n" 
    fi 

    # Check that dir is in the user’s PATH. 
    case ":$PATH:" in 
    *:"$dir":*) 
     printf "‘%s’ is in the PATH.\n" "$dir" 
     return 0 
     ;; 
    *) 
     printf "‘%s’ is not in the PATH.\n" "$dir" 
     return 1 
     ;; 
    esac 
} 

हिस्सा :$PATH: का उपयोग कर यह सुनिश्चित करता है अगर वांछित पथ PATH में पहली या अंतिम प्रविष्टि है पैटर्न भी मेल खाता है। यह चालाक चाल this answer by Glenn Jackman on Unix & Linux पर आधारित है।

0

इसके लिए बाहरी उपयोगिताओं जैसे grep का उपयोग करने की बिल्कुल आवश्यकता नहीं है। यहां मैं जो उपयोग कर रहा हूं, वह बोर्न शैल के विरासत संस्करणों तक वापस पोर्टेबल होना चाहिए।

case :$PATH: # notice colons around the value 
    in *:$HOME/bin:*) ;; # do nothing, it's there 
    *) echo "$HOME/bin not in $PATH" >&2;; 
esac