Usuń nadmiarowe ścieżki ze zmiennej $ PATH


125

Zdefiniowałem tę samą ścieżkę w zmiennej $ PATH 6 razy.

Nie wylogowywałem się, żeby sprawdzić, czy zadziałało.

Jak mogę usunąć duplikaty?

Zmienna $ PATH wygląda następująco:

echo $PATH

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin:/home/flacs/Programmes/USFOS/bin

Jak bym zresetował to do just

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

gdzie zdefiniowałeś to 6 razy? w jakich plikach?
hovanessyan


Odpowiedzi:


122

Po prostu wykonujesz:

export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

dotyczy to bieżącej sesji, jeśli chcesz zmienić na stałe, dodaj ją do dowolnego pliku .bashrc, bash.bashrc, / etc / profile - cokolwiek pasuje do twojego systemu i potrzeb użytkownika.

Uwaga: dotyczy to systemu Linux. Wyjaśnimy to nowym programistom. (`, ') Nie próbuj ustawiać = tych.


tak, ustawiłem je na stałe w bash.bashrc. Czy więc polecenie powinno wyglądać mniej więcej tak? echo 'export PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games' >> ~/.bashrc
charles hendry

chodzi o to, że w zależności od systemu operacyjnego wykonywany jest łańcuch konfiguracji. Musisz upewnić się, że zmienna PATH nie zostanie później nadpisana. Najłatwiejszym sposobem (dla jednego użytkownika) jest nadpisanie go w osobistym pliku .bashrc użytkownika, który zwykle znajduje się w jego katalogu domowym.
hovanessyan

1
twoje polecenie ustawia PATH na - $ PATH (bieżąca wartość PATH) + ciąg / usr / local / sbin: / usr / local / bin: / usr / sbin: / usr / bin: / sbin: / bin: / usr / gam‌ es. Jeśli chcesz mieć tylko łańcuch, usuń $ PATH + średnik (:) z polecenia. Nie ma znaczenia, czy używasz echo, czy ręcznie edytujesz plik ~ / .bashrc.
hovanessyan

plik bash.bashrc znajduje się w folderze / etc. Nie wyświetla jednak zmiennej $ PATH, więc nie jestem pewien, gdzie ją edytować
Charles Hendry

w swoim pierwszym komentarzu odbierasz echo do ~ / .bashrc (cytując: >> ~ / .bashrc), a nie do /etc/bash.bashrc. Jeśli chcesz zmienić ŚCIEŻKĘ dla określonego użytkownika, edytuj ją w / home / <nazwa użytkownika> /. Bashrc. /etc/bash.bashrc dotyczy wszystkich użytkowników.
hovanessyan

70

Jeśli używasz Bash, możesz również wykonać następujące czynności, jeśli, powiedzmy, chcesz usunąć katalog /home/wrong/dir/ze swojej PATHzmiennej:

PATH=`echo $PATH | sed -e 's/:\/home\/wrong\/dir\/$//'`

1
Było to dla mnie przydatne, ponieważ w / etc / profile został dodany katalog, który chciałem wykluczyć, ale nie mam dostępu do / etc. Dzięki :)
Samizdis

13
Protip: możesz użyć innego separatora w wyrażeniu sed, aby uniknąć PATH=$(echo $PATH | sed -e 's|:/home/wrong/dir|$||')
znaku

4
Ta sztuczka pomaga, gdy chcę od razu mieć nową ścieżkę PATH i nie chcę wylogowywać się z bieżącego terminala. Jednak, aby uniknąć pomyłek, należy poeksperymentować z poleceniem generującym PATH (tj. echo $PATH | sed -e 's/:\/home\/wrong\/dir\/$//') Przed przypisaniem go do PATH.
biocyberman

2
To nie zadziała, jeśli ścieżka do usunięcia jest pierwszą ścieżką w $PATH. Użyj tego:PATH=$(echo :$PATH: | sed -e 's,:/home/wrong/dir:,:,g' -e 's/^://' -e 's/:$//')
Robin Hsu,

nie działało $ PATH=echo $ PATH | sed -e 's /: \ / scratch \ / sjn \ / anaconda \ / bin \ / python \ / $ //' '`` do usuwania / scratch / sjn / anaconda / bin / python
Mona Jalal

13

Linux: Usuń nadmiarowe ścieżki ze zmiennej $ PATH

Linux From Scratch ma tę funkcję w / etc / profile

# Functions to help us manage paths.  Second argument is the name of the
# path variable to be modified (default: PATH)
pathremove () {
        local IFS=':'
        local NEWPATH
        local DIR
        local PATHVARIABLE=${2:-PATH}
        for DIR in ${!PATHVARIABLE} ; do
                if [ "$DIR" != "$1" ] ; then
                  NEWPATH=${NEWPATH:+$NEWPATH:}$DIR
                fi
        done
        export $PATHVARIABLE="$NEWPATH"
}

Ma to być używane z tymi funkcjami do dodawania do ścieżki, aby nie robić tego nadmiarowo:

pathprepend () {
        pathremove $1 $2
        local PATHVARIABLE=${2:-PATH}
        export $PATHVARIABLE="$1${!PATHVARIABLE:+:${!PATHVARIABLE}}"
}

pathappend () {
        pathremove $1 $2
        local PATHVARIABLE=${2:-PATH}
        export $PATHVARIABLE="${!PATHVARIABLE:+${!PATHVARIABLE}:}$1"
}

Prostym użyciem jest po prostu podanie pathremoveścieżki katalogu do usunięcia - ale pamiętaj, że musi ona dokładnie pasować:

$ pathremove /home/username/anaconda3/bin

Spowoduje to usunięcie każdej instancji tego katalogu ze ścieżki.

Jeśli chcesz, aby katalog znajdował się w Twojej ścieżce, ale bez redundancji, możesz po prostu użyć jednej z pozostałych funkcji, np. - w swoim konkretnym przypadku:

$ pathprepend /usr/local/sbin
$ pathappend /usr/local/bin
$ pathappend /usr/sbin
$ pathappend /usr/bin
$ pathappend /sbin
$ pathappend /bin
$ pathappend /usr/games

Ale o ile czytelność nie jest problemem, w tym momencie lepiej po prostu zrobić:

$ export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

Czy powyższe zadziałałoby we wszystkich powłokach znanych człowiekowi?

Chciałbym przypuszczać powyższego do pracy w sh, dashi bashprzynajmniej. Byłbym zaskoczony, gdyby się dowiedział, że to nie działa csh, fish', orksh`. Wątpię, czy zadziałaby w powłoce poleceń Windows lub w Powershell.

Jeśli masz Pythona, poniższe polecenie powinno zrobić to, o co bezpośrednio zapytano (czyli usunąć nadmiarowe ścieżki):

$ PATH=$( python -c "
import os
path = os.environ['PATH'].split(':')
print(':'.join(sorted(set(path), key=path.index)))
" )

Jednowierszowy (aby uniknąć problemów wielowierszowych):

$ PATH=$( python -c "import os; path = os.environ['PATH'].split(':'); print(':'.join(sorted(set(path), key=path.index)))" )

Powyższe usuwa później zbędne ścieżki. Aby usunąć wcześniejsze nadmiarowe ścieżki, użyj indeksu odwróconej listy i ponownie go odwróć:

$ PATH=$( python -c "
import os
path = os.environ['PATH'].split(':')[::-1]
print(':'.join(sorted(set(path), key=path.index, reverse=True)))
" )

+1. czy pathremove () działa we wszystkich smakach powłoki, takich jak csh, ksh, bash itp? btw, mój / etc / profile na RHEL nie ma partremove (), ale ma tylko pathmunge ().
Tagar

1
@Tagar Nie gwarantuję zgodności ze wszystkimi innymi powłokami. Proponuję przetestować go na dowolnej powłoce, której używasz, a jeśli nie działa dla twojej powłoki, możesz użyć Pythona, jeśli masz go zainstalowanego - dodałem trochę Pythona do odpowiedzi, aby opisać, jak to zrobić.
Aaron Hall

Jeśli poprawnie przeczytałem „3.5.3 Rozszerzanie parametrów powłoki”, ${!PATHVARIABLE}jest to rodzaj zmiennej pośredniej, ale nie jestem pewien, jak to działa tutaj. Czy mógłbyś to wyjaśnić?
loxaxs

@loxaxs To lokalna zmienna w tych funkcjach basha, zadeklarowana za pomocą funkcji localwbudowanej (której można używać tylko wewnątrz funkcji). Jeśli masz dalsze pytania, prawdopodobnie powinieneś zadać nowe pytanie na stronie (po wyszukaniu go najpierw, aby upewnić się, że nie tworzysz dokładnego duplikatu ...).
Aaron Hall

To naprawdę ciekawa odpowiedź, dzięki za napisanie! Jednak pierwotna kwestia wyczyszczenia pomieszanej zmiennej PATH nie wydaje się być elegancko rozwiązana (chociaż, przyznaję, wtedy podczas korzystania z tych funkcji nie skończyłoby się pomieszaniem PATH).
Christian Herenz

9

Oto jeden wiersz kodu, który czyści PATH

  • Nie zakłóca kolejności PATH, po prostu usuwa duplikaty
  • Smakuje: i z wdziękiem emanuje PATH
  • Brak znaków specjalnych, więc nie wymaga ucieczki
  • Używa, /bin/awkwięc działa nawet wtedy, gdy PATH jest uszkodzony

    export PATH="$(echo "$PATH" |/bin/awk 'BEGIN{RS=":";}
    {sub(sprintf("%c$",10),"");if(A[$0]){}else{A[$0]=1;
    printf(((NR==1)?"":":")$0)}}')";

1
ktoś to przetestował? jest bezpieczny?
Joe RR

2
jeśli nie masz zainstalowanego awk czyści swoją ścieżkę, radzę Kopiowanie ścieżkę do pliku txt, zanim z echo $ PATH
José Pita

Nie działa dla mnie ... Mam zainstalowany awk, ale niektóre duplikaty nie są usuwane.
Christian Herenz,

3
  1. Właśnie echo $PATH
  2. skopiuj szczegóły do ​​edytora tekstu
  3. usuń niechciane wpisy
  4. PATH= # pass new list of entries

2

Jeśli chcesz tylko usunąć zduplikowane ścieżki, używam tego skryptu, który napisałem jakiś czas temu, ponieważ miałem problem z wieloma ścieżkami perl5 / bin:

#!/bin/bash
#
# path-cleanup
#
# This must be run as "source path-cleanup" or ". path-cleanup"
# so the current shell gets the changes.

pathlist=`echo $PATH | sed 's/:/\n/g' | uniq`

# echo "Starting PATH: $PATH"
# echo "pathlist: $pathlist"
unset PATH
# echo "After unset, PATH: $PATH"
for dir in $pathlist
do
    if test -d $dir ; then
        if test -z $PATH; then
            PATH=$dir
        else
            PATH=$PATH:$dir
        fi
    fi
done
export PATH
# echo "After loop, PATH: $PATH"

I umieściłem to w moim ~ / .profile na końcu. Ponieważ używam BASH prawie wyłącznie, nie próbowałem go w innych powłokach.


1
+1 za rozwiązanie. Przy okazji, usunie ścieżki duplikatów tylko wtedy, gdy pojawią się na liście jedna po drugiej. Możesz zmienić |uniqna, |sort|uniqaby to naprawić, ale spowoduje to zmianę kolejności wszystkich katalogów w ścieżce, co moim zdaniem nie jest pożądanym efektem ubocznym.
Tagar

1

Zakładając, że twoja powłoka to Bash, możesz ustawić ścieżkę za pomocą

export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

ale jak powiedział Levon w innej odpowiedzi, jak tylko zakończysz działanie powłoki, zmiany znikną. Prawdopodobnie chcesz skonfigurować swój PATHw ~/.bash_profilelub ~/.bashrc.


1

W bashu możesz po prostu $ {var / find / replace}

PATH=${PATH/%:\/home\/wrong\/dir\//}

Lub w tym przypadku (ponieważ bit wymiany jest pusty) po prostu:

PATH=${PATH%:\/home\/wrong\/dir\/}

Przyjechałem tutaj pierwszy, ale poszedłem dalej, ponieważ myślałem, że nastąpi rozszerzenie parametrów aby to zrobić. Łatwiejsze niż sed !.

Jak zamienić znak zastępczy lub słowo w zmiennej na wartość z innej zmiennej w Bash?


%oznacza dopasowanie, jeśli na końcu łańcucha, #jest na początku.
Sabgenton

0

Nie ma standardowych narzędzi do „edycji” wartości $PATH(np. „Dodaj folder tylko wtedy, gdy jeszcze nie istnieje” lub „usuń ten folder”).

Aby sprawdzić, jaka byłaby ścieżka podczas następnego logowania, użyj telnet localhost(lub telnet 127.0.0.1). Następnie poprosi o podanie nazwy użytkownika i hasła.

To daje ci nową powłokę logowania (tj. Zupełnie nową, która nie dziedziczy niczego z obecnego środowiska).

Możesz sprawdzić wartość $PATHtam i edytować pliki rc, aż będzie poprawna. Jest to również przydatne, aby sprawdzić, czy w ogóle możesz się zalogować ponownie po wprowadzeniu zmiany w ważnym pliku.


Zamiast wpisywać nazwę użytkownika / hasło, po prostu wpisz /bin/bash -i. Dużo mniej kłopotów.
Ed Heal

0

Jak dodałeś te zduplikowane ścieżki do zmiennej PATH? Musisz edytować jeden ze swoich .plików. ( .tcshrclub .bashrc, itp., w zależności od konkretnego systemu / powłoki). Aby to naprawić, należy ponownie wyedytować plik i usunąć zduplikowane ścieżki.

Jeśli nie edytowałeś żadnych plików i musisz interaktywnie zmodyfikować PATH. W takim przypadku zmiany nie zostaną „zachowane”, tj. Jeśli otworzysz inną powłokę lub wylogujesz się i zalogujesz ponownie, zmiany znikną automatycznie.

Zauważ, że istnieją również pliki konfiguracyjne dla całego systemu, ale jest mało prawdopodobne, że je zmodyfikowałeś, więc najprawdopodobniej będziesz zmieniać pliki w swoim osobistym katalogu domowym (jeśli chcesz, aby te zmiany stały się trwałe po ustaleniu zestawu ścieżek)


0

Aby uzyskać łatwy szablon kopiuj-wklej, używam tego fragmentu kodu Perl:

PATH=`echo $PATH | perl -pe s:/path/to/be/excluded::`

W ten sposób nie musisz uciekać przed ukośnikami dla operatora zastępczego.

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.