Zduplikowane wpisy w $ PATH problem?


45

Pozyskuję bashrc kilku moich przyjaciół. Mam więc zduplikowane wpisy w mojej zmiennej $ PATH. Nie jestem pewien, czy taki jest problem w przypadku poleceń, których uruchomienie trwa długo. Jak $ PATH działa wewnętrznie w bash? Czy posiadanie większej liczby ŚCIEŻEK spowalnia mój czas uruchamiania?




Odpowiedzi:


42

Posiadanie większej liczby wpisów $PATHnie spowalnia bezpośrednio uruchamiania, ale spowalnia za każdym razem, gdy po raz pierwszy uruchamiasz określone polecenie w sesji powłoki (nie za każdym razem, gdy uruchamiasz polecenie, ponieważ bash utrzymuje pamięć podręczną). Spowolnienie jest rzadko wyczuwalne, chyba że masz szczególnie wolny system plików (np. NFS, Samba lub inny sieciowy system plików lub Cygwin).

Zduplikowane wpisy są również trochę denerwujące, gdy przeglądasz $PATHwizualnie, musisz przedzierać się przez więcej cruft.

Łatwo jest uniknąć dodawania duplikatów.

case ":$PATH:" in
  *":$new_entry:"*) :;; # already there
  *) PATH="$new_entry:$PATH";; # or PATH="$PATH:$new_entry"
esac

Uwaga dodatkowa: pozyskiwanie czyichś skryptów powłoki oznacza wykonywanie napisanego przez siebie kodu. Innymi słowy, dajesz swoim znajomym dostęp do konta, kiedy tylko chcą.

Uwaga dodatkowa: .bashrcnie jest właściwym miejscem do ustawienia $PATHlub jakiejkolwiek innej zmiennej środowiskowej. Zmienne środowiskowe powinny być ustawione w ~/.profile. Zobacz Które pliki instalacyjne powinny być używane do konfigurowania zmiennych środowiskowych za pomocą bash? , Różnica między .bashrc i .bash_profile .


8
+1: nie mogę podkreślić, że „zapewnienie swoim znajomym dostępu do twojego konta” wystarcza. Nawet jeśli nie próbujesz wyrządzić ci krzywdy, ich skrypt może być dokładnie tym, czego potrzebują i nadal jeść lunch, gdy go zdobędziesz.
msw

Jednym z możliwych problemów z tym rozwiązaniem jest to, że jeśli $ new_entry jest już pierwszym wpisem w PATH, „: $ new_entry:” nie będzie pasować. Naprawiłem to w moim profilu, wykluczając początkowy dwukropek „:”.
Jeff Bauer

@JeffBauer Nie widzę problemu. Używam case :$PATH:i nie case $PATHtak, że pasuje, nawet jeśli wpis jest pierwszy lub ostatni.
Gilles „SO- przestań być zły”

31

Widziałem, jak ludzie usuwają duplikaty ze swojej zmiennej PATH awki używają czegoś takiego:

PATH=$(printf "%s" "$PATH" | awk -v RS=':' '!a[$1]++ { if (NR > 1) printf RS; printf $1 }')

Możesz spróbować dodać to do własnego bashrc i upewnić się, że gdzieś pozyskałeś inne pliki przed uruchomieniem.

Alternatywą byłoby użyć napathmerge użyteczność.

Jeśli chodzi o problem z szybkością, nie wpłynie to znacząco na czas uruchamiania powłoki, ale może zaoszczędzić trochę czasu na wykonywaniu poleceń tabulacji dla poleceń, szczególnie gdy polecenie nie zostanie znalezione na ścieżce i powtórzy przeszukiwanie tego samego szukają folderów.

Uwaga na temat bezpieczeństwa: powinieneś naprawdę wziąć pod uwagę ostrzeżenia Gillesa dotyczące bezpieczeństwa tutaj. Pozyskując plik należący do innego użytkownika, dajesz tym użytkownikom bezpłatne hasło do wykonania własnego kodu jako użytkownik za każdym razem, gdy uruchamiasz powłokę. Jeśli nie ufasz tym użytkownikom swoim hasłem, nie powinieneś pozyskiwać ich plików powłoki.


6
Lubię awk one-liner, ale drukuje tylną ORS „:”. Więc zmodyfikowałem go do odczytuPATH=$(echo "$PATH" | awk -v RS=':' -v ORS=":" '!a[$1]++{if (NR > 1) printf ORS; printf $a[$1]}')
gkb0986,

Trailing :to nie tylko kwestia kosmetyczna. Jest to to samo, co dodawanie .do ścieżki, co jest potencjalnie niebezpieczne.
wisbucky 24.04.17

Zredagowałem odpowiedź, aby załączyć poprawkę z gkb0986.
Tim Lesher

@TimLesher Powodem, dla którego nigdy nie edytowałem w odpowiedzi, jest to, że nie działa dla mnie .... a oryginał bez niego działa (w tym nie pozostawia separatora końcowego. Nie wiem, jaka jest różnica .
Caleb

1
@ gkb0986 To rozwiązanie nadal nie działa, jeśli ścieżka zawiera spację, na przykład PATH = / bin: / foo \ bar: / usr / bin. Znalazłem wariant, który pozwala tego uniknąć na unix.stackexchange.com/a/124517/106102
maharvey67

13

Na podstawie odpowiedzi @Gilles możesz zawinąć ją w funkcję, aby zminimalizować pisanie:

function addToPATH {
  case ":$PATH:" in
    *":$1:"*) :;; # already there
    *) PATH="$1:$PATH";; # or PATH="$PATH:$1"
  esac
}

addToPATH /Applications/AIRSDK_Compiler/bin
addToPATH ~/.local/lib/npm/bin

1
Najbardziej praktyczna (prawdopodobnie na wysokim poziomie) odpowiedź.
ijoseph

3

Wykonywane jest tylko pierwsze dopasowanie $PATH, więc późniejsze wpisy nie są przetwarzane. Dlatego czasami powinieneś zmieniać kolejność wpisów w $PATHswoim środowisku, aby środowisko działało zgodnie z oczekiwaniami.

Aby odpowiedzieć na twoje pytanie: nie powinno to być przyczyną wolnego uruchamiania.


1
Ale to trwa dłużej, gdy wpisuję polecenie, które nie istnieje. Polecenie przeszuka ten sam folder dwukrotnie.
balki

@balki Masz na myśli wykonanie polecenia za pomocą TAB? W takim przypadku powinieneś sprawdzić, czy uzupełnienie definicji nie wygląda complete -c which -a. Powinieneś usunąć -aparametr. Można sprawdzić, że wydając polecenie: complete | grep which.
Rajish

Problem może nadal występować, jeśli przeszuka ten sam katalog, którego nie ma wiele razy, zanim go znajdzie.
Random832

-1

Aby zapobiec powielaniu wpisów w mojej ŚCIEŻCE, musiałem umieścić OBA w ~ / .bash_profile i ~ / .bashrc:

PATH=$(echo $(sed 's/:/\n/g' <<< $PATH | sort | uniq) | sed -e 's/\s/':'/g')

Główną wadą jest to, że sortuje wpisy PATH, ale myślę, że mogę z tym żyć.


Kolejność ŚCIEŻKI wyszukiwania jest bardzo ważna.
Steven Shaw
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.