PATH वैरिएबल से डुप्लिकेट प्रविष्टियाँ


9

मैं अपने .bashrc को बार-बार संशोधित करता हूं और फिर उसे स्रोत बनाता हूं। हालांकि, जब मेरे पास export PATH="~/bin:~/perl5/bin:$PATH"मेरी फ़ाइल जैसी चीजें होती हैं , तो PATHहर बार जब मैं फ़ाइल को स्रोत करता हूं तो पर्यावरण चर बढ़ता है।

उदाहरण के लिए, पहली बार .bashrc को सोर्स किया गया है, जिसमें PATHचर शामिल हैं ~/bin:~/perl5/bin:/usr/bin:/bin

दूसरी बार इसमें शामिल हैं ~/bin:~/perl5/bin:~/bin:~/perl5/bin:/usr/bin:/bin

तीसरी बार इसमें शामिल हैं ~/bin:~/perl5/bin:~/bin:~/perl5/bin:~/bin:~/perl5/bin:/usr/bin:/bin

वहाँ एक आसान तरीका है कि यह केवल कुछ भी है कि पहले से ही पेट में नहीं है बनाने के लिए है?

जवाबों:


12

सबसे अधिक डिस्ट्रो में उपलब्ध पथमुनगे () फ़ंक्शन का उपयोग करें /etc/profile:

pathmunge () {
if ! echo $PATH | /bin/egrep -q "(^|:)$1($|:)" ; then
   if [ "$2" = "after" ] ; then
      PATH=$PATH:$1
   else
      PATH=$1:$PATH
   fi
fi
}

संपादित करें : zshउपयोगकर्ताओं के लिए, typeset -U <variable_name>पथ प्रविष्टियों को काट देगा।


धन्यवाद! यह /etc/profileडेबियन लेनी पर नहीं है , इसलिए मैं इसे अपने में शामिल करता हूं .bashrc
क्रिस्टोफर बॉटलम्स

उपयोग: pathmunge /some/pathस्थापित करेंगे /some/pathकी शुरुआत में $PATHऔर pathmunge /some/path afterस्थापित करेंगे /some/pathके अंत में$PATH
क्रिस्टोफर बॉटम्स

चेक को करने का साफ तरीका यह देखने के लिए कि क्या हैश निर्देशिका वर्तमान पथ में मौजूद है, आधुनिक बैश शेल में if ! [[ $PATH =~ (^|:)$1($|:) ]] ; then:।
क्रिस्टोफर काशेल

मैं इस का उपयोग नहीं करेगा। यदि मेरे भोले संस्करण ने PATH = / foo: $ PATH कहा है जिसका अर्थ है कि मैं जीतना चाहता हूं / foo। pathmunge /foo beforeवह पूरा नहीं करता है। एक बेहतर तरीका यह होगा कि शुरुआत में / foo जोड़ें और बाद में डुप्लिकेट को हटा दें।
डॉन हैच

3

मुझे यह समस्या आ रही थी इसलिए मैंने StackOverflow सवाल पर सूचीबद्ध तकनीकों के संयोजन का उपयोग किया । निम्नलिखित वह है जो मैं पहले से निर्धारित किए गए वास्तविक पैथ चर को कम करने के लिए उपयोग करता था, क्योंकि मैं आधार स्क्रिप्ट को संशोधित नहीं करना चाहता था।

    tmppath=(${PATH// /@})
    array=(${tmppath//:/ })
    for i in "${array[@]//@/ }"
    do
        if ! [[ $PATH_NEW =~ "$i" ]]; then
            PATH_NEW="${PATH_NEW}$i:";
        fi
    done;
    PATH="${PATH_NEW%:}"
    export PATH
    unset PATH_NEW

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

  1. किसी SPACE के वर्ण को किसी @ वर्ण से बदलें
  2. सरणी को विभाजित करें
  3. सरणी के माध्यम से लूप
  4. तत्व स्ट्रिंग में किसी भी @ अक्षर को एक स्थान से बदलें

यह सुनिश्चित करने के लिए है कि मैं (Samba घर निर्देशिकाओं को सक्रिय निर्देशिका उपयोगकर्ता नामों के साथ स्थान हो सकता है!)


चेतावनी: इस कार्यान्वयन में एक प्रमुख बग है !! /binयदि अन्य प्रविष्टियाँ समान हैं, तो यह हटा देगा /usr/binक्योंकि regexp मेल खाता है, भले ही दोनों प्रविष्टियाँ समान न हों!
सुकिमा

यहाँ एक वैकल्पिक कार्यान्वयन है जो उस बग को ठीक करता है: github.com/sukima/dotfiles/blob/…
Sukima

1

अपना रास्ता स्पष्ट रूप से निर्धारित करें।


धन्यवाद। मैंने स्पष्ट रूप से पथ सेट करने की कोशिश की, लेकिन मेरे पास एक .bashrc फ़ाइल है जिसे मैं कई वातावरणों में उपयोग करता हूं, इसलिए सटीक डिफ़ॉल्ट PATHहमेशा समान नहीं होता है।
क्रिस्टोफर बॉटम्स

1

केवल एक स्ट्रिंग:

for i in $(echo $PATH|tr ":" "\n"|sort|uniq);do PATH_NEW="${PATH_NEW}$i:";done;PATH="${PATH_NEW%:}"

धन्यवाद। एक मुश्किल से यह मेरे कारण होता है कि यह वर्णानुक्रम में (या ASCIIbetically) की सामग्री को पुनर्स्थापित करता है $PATH। मैं $PATH(जैसे /home/username) की शुरुआत में विशिष्ट निर्देशिकाओं को रखना पसंद करता हूं ताकि मेरे व्यक्तिगत निष्पादन की प्रतियां अंतर्निहित दोषों के बजाय चलें।
क्रिस्टोफर बॉटम्स

1

मैं इसे हल करने के दो अलग-अलग तरीकों के बारे में सोच सकता हूं। पहला, अपने .bashrc को एक लाइन के साथ शुरू करना है जो स्पष्ट रूप से आपके आधार को सेट करता है PATH, इस तरह हर बार जब आप इसे स्रोत करते हैं, तो अतिरिक्त निर्देशिकाओं को जोड़ने से पहले इसे आधार पर रीसेट कर दिया जाता है।

उदाहरण के लिए, जोड़ें:

# Reset the PATH to prevent duplication and to make sure that we include
# everything we want.
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

वैकल्पिक रूप से, आप पथ में जोड़ने से पहले किसी आइटम की जांच कर सकते हैं। ऐसा करने के लिए, आप कुछ का उपयोग करेंगे:

if ! [[ $PATH =~ '~/perl5/bin' ]]
then
    PATH="~/perl5/bin:$PATH"
fi

उत्तरार्द्ध थोड़ा दोहराव पाने के लिए जाता है यदि आप बहुत सारी प्रविष्टियां जोड़ रहे हैं, हालांकि, इसलिए मैं पूर्व के साथ रहना चाहता हूं। यदि आप इसका उपयोग करना चाहते हैं और बहुत सारी प्रविष्टियों को जोड़ने की योजना बनाई है, तो इसे संभालने के लिए एक बश फ़ंक्शन लिखना।

नोट: दूसरा विकल्प केवल आधुनिक संस्करणों बैश में लिखे अनुसार काम कर सकता है। नियमित अभिव्यक्ति समर्थन बॉर्न शेल (/ बिन / श) सुविधा नहीं है, और अन्य शेल में मौजूद नहीं हो सकता है। इसके अलावा, उद्धरणों के उपयोग की आवश्यकता नहीं हो सकती है या बैश के कुछ नवीनतम संस्करणों पर भी समस्या हो सकती है।


धन्यवाद। मैंने स्पष्ट रूप से पथ सेट करने की कोशिश की, लेकिन मेरे पास एक .bashrc फ़ाइल है जिसे मैं कई वातावरणों में उपयोग करता हूं, इसलिए सटीक डिफ़ॉल्ट PATHहमेशा समान नहीं होता है।
क्रिस्टोफर बॉटम्स

आप अभी भी संभाल सकते हैं कि स्क्रिप्ट में जाँच करके देखें कि आपका स्थानीय होस्टनाम क्या है, और फिर उस सर्वर के लिए उचित तरीके से अपना संपूर्ण पथ सेट करें।
क्रिस्टोफर कैशेल

बस एक टाइपो: ए! में गायब है if। इसके अलावा, यह आश्चर्यजनक रूप से (मेरे लिए) एक फंक्शन में बनाना आसान है, जो स्पेस-अलग-अलग तर्कों पर लूप करता है, इसलिए आप बस कह सकते हैं: add_to_PATH ~/perl5/bin ~/.bin unix.stackexchange.com/a/4973/28760 (मुझे लगता है कि caseवहां इस्तेमाल किया गया बयान अधिक पोर्टेबल है , लेकिन आपके ifलिए मेरे लिए स्पष्ट है)। EDIT अजीब संयोग है कि सवाल भी perl5 कहते हैं!
13ren

@ 13ren: नोट के लिए धन्यवाद। मुझे यह भी एहसास हुआ कि मैंने पाथ सेट लाइन में सिंगल कोट्स का इस्तेमाल किया, जैसे मुझे होना चाहिए था। जैसा कि लिखा गया है, यह आपके मौजूदा मार्ग को परिवर्तनशील नाम से बदल देगा। ऊप्स! जाहिर है कि टाइपो के लिए मेरे लिए एक बुरी प्रविष्टि थी; दोनों अब तय हो गए हैं।
क्रिस्टोफर कैशेल

0

यहाँ मेरा समाधान है: PATH=$(echo -n $PATH | awk -v RS=: -v ORS=: '!x[$0]++' | sed "s/\(.*\).\{1\}/\1/")

एक अच्छा आसान एक लाइनर जो एक अनुगामी नहीं छोड़ता है:

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.