Rimuovere i percorsi ridondanti dalla variabile $ PATH


125

Ho definito lo stesso percorso nella variabile $ PATH 6 volte.

Non stavo uscendo per verificare se funzionava.

Come posso rimuovere i duplicati?

La variabile $ PATH si presenta così:

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

Come lo ripristinerei a solo

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

dove l'hai definito 6 volte? in quali file?
hovanessyan,


Risposte:


122

Devi solo eseguire:

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

questo sarebbe per la sessione corrente, se vuoi cambiarlo permanentemente aggiungilo a qualsiasi profilo .bashrc, bash.bashrc, / etc / profile - qualunque cosa si adatti al tuo sistema e alle tue esigenze dell'utente.

Nota: questo è per Linux. Lo chiariremo per i nuovi programmatori. (`, ') Non provare a impostare = questi.


sì, li ho impostati permanentemente in bash.bashrc. Quindi il comando dovrebbe essere qualcosa del genere? echo 'export PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games' >> ~/.bashrc
charles hendry il

il fatto è che a seconda del sistema operativo in uso viene eseguita una catena di configurazioni. È necessario assicurarsi che la variabile PATH non venga sovrascritta in seguito. Il modo più semplice per farlo (per un utente) è sovrascriverlo nel .bashrc personale dell'utente, che di solito si trova nella sua directory home.
hovanessyan,

1
il tuo comando imposta PATH su - $ PATH (il valore corrente di PATH) + la stringa / usr / local / sbin: / usr / local / bin: / usr / sbin: / usr / bin: / sbin: / bin: / usr / gam es. Se vuoi avere solo la stringa, rimuovi $ PATH + il punto e virgola (:) dal tuo comando. Non importa se usi echo o modifichi il file ~ / .bashrc manualmente.
hovanessyan,

il file bash.bashrc si trova nella cartella / etc. Tuttavia, non visualizza la variabile $ PATH, quindi non sono sicuro di dove modificarlo
charles hendry

nel tuo primo commento fai eco a ~ / .bashrc (citando: >> ~ / .bashrc), non a /etc/bash.bashrc. Se vuoi cambiare il PERCORSO per un utente specifico, modificalo nel file / home / <il nome dell'utente> /. Bashrc. il /etc/bash.bashrc si applica a tutti gli utenti.
hovanessyan,

70

Se stai usando Bash, puoi anche fare quanto segue se, diciamo, vuoi rimuovere la directory /home/wrong/dir/dalla tua PATHvariabile:

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

1
Questo mi è stato utile, poiché è stata aggiunta una directory in / etc / profile che volevo escludere, ma non ho accesso in scrittura a / etc. Grazie :)
Samizdis,

13
Protip: puoi usare diversi deliminatori nell'espressione sed per evitare il \ / escape:PATH=$(echo $PATH | sed -e 's|:/home/wrong/dir|$||')
iNecas

4
Questo trucco aiuta quando voglio avere subito un nuovo PERCORSO e non voglio disconnettermi dal terminale corrente. Tuttavia, per evitare di incasinare, si dovrebbe sperimentare il comando di generazione PATH (cioè echo $PATH | sed -e 's/:\/home\/wrong\/dir\/$//') prima di assegnarlo a PATH.
biocyberman,

2
Questo non funzionerà quando il percorso da eliminare sembra essere il 1 ° percorso in $PATH. Usa questo:PATH=$(echo :$PATH: | sed -e 's,:/home/wrong/dir:,:,g' -e 's/^://' -e 's/:$//')
Robin Hsu il

non ha funzionato $ PATH=echo $ PATH | sed -e 's /: \ / scratch \ / sjn \ / anaconda \ / bin \ / python \ / $ //' '`per rimuovere / scratch / sjn / anaconda / bin / python
Mona Jalal

13

Linux: rimuove i percorsi ridondanti dalla variabile $ PATH

Linux From Scratch ha questa funzione in / 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"
}

Questo è destinato a essere utilizzato con queste funzioni per l'aggiunta al percorso, in modo da non farlo in modo ridondante:

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"
}

L'utilizzo semplice consiste semplicemente nel fornire pathremoveil percorso della directory da rimuovere, ma tieni presente che deve corrispondere esattamente:

$ pathremove /home/username/anaconda3/bin

Ciò rimuoverà ogni istanza di quella directory dal tuo percorso.

Se vuoi la directory nel tuo percorso, ma senza le ridondanze, puoi semplicemente usare una delle altre funzioni, ad esempio - per il tuo caso specifico:

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

Ma, a meno che la leggibilità non sia preoccupante, a questo punto è meglio fare semplicemente:

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

Quanto sopra funzionerebbe in tutte le conchiglie conosciute dall'uomo?

Vorrei presumere quanto sopra per il lavoro in sh, dashe bashalmeno. Sarei sorpreso di apprendere che non funziona csh, fish', orksh`. Dubito che funzionerebbe nella shell dei comandi di Windows o Powershell.

Se si dispone di Python, il seguente tipo di comando dovrebbe eseguire ciò che viene richiesto direttamente (ovvero rimuovere i percorsi ridondanti):

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

Un one-liner (per evitare problemi multilinea):

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

Quanto sopra rimuove i percorsi ridondanti successivi. Per rimuovere percorsi ridondanti precedenti, utilizzare l'indice di un elenco invertito e invertirlo di nuovo:

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

+1. pathremove () funziona in tutti i tipi di shell, come csh, ksh, bash ecc? btw, il mio / etc / profilo su RHEL non ha partremove (), ma ha solo pathmunge ().
Tagar,

1
@Tagar Non garantisco la compatibilità con tutte le altre shell. Suggerisco di provarlo su qualunque shell tu stia usando, e se non funziona per la tua shell, puoi usare Python se lo hai installato - Ho aggiunto un po 'di Python alla risposta per descrivere come.
Aaron Hall

Se ho letto correttamente "3.5.3 Shell Parameter Expansion", ${!PATHVARIABLE}è una specie di variabile indiretta, ma non sono sicuro di come funzioni qui. Potresti spiegarlo per favore?
Loxaxs

@loxaxs Questa è una variabile locale in quelle funzioni bash, dichiarata con il localbuiltin (che può essere usato solo all'interno di una funzione.) Se hai ulteriori domande, dovresti probabilmente fare una nuova domanda sul sito (dopo averla cercata prima per assicurarti non stai creando un duplicato esatto ...).
Aaron Hall

Questa è una risposta davvero interessante, grazie per il writeup! Tuttavia, la domanda originale di ripulire una variabile PATH incasinata sembra non essere risolta elegantemente (anche se, ammetto, quindi quando si utilizzano queste funzioni non si finirebbe con un PATH incasinato per cominciare).
Christian Herenz,

9

Ecco un codice a una riga che pulisce il PERCORSO

  • Non disturba l'ordine del PERCORSO, rimuove solo i duplicati
  • Dolcetti: e svuota il PERCORSO con grazia
  • Non sono stati usati caratteri speciali, quindi non è necessario scappare
  • Usa /bin/awkcosì funziona anche quando il PERCORSO è rotto

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

1
qualcuno l'ha provato? è salvo?
Joe RR

2
se non hai installato awk pulisce il tuo percorso, ti consiglio di copiare il tuo percorso in un file txt prima con echo $ PATH
Jose Pita

Non funziona per me ... Ho installato awk, ma alcuni duplicati non vengono rimossi.
Christian Herenz,

3
  1. Appena echo $PATH
  2. copiare i dettagli in un editor di testo
  3. rimuovere le voci indesiderate
  4. PATH= # pass new list of entries

2

Se vuoi solo rimuovere percorsi duplicati, uso questo script che ho scritto qualche tempo fa poiché avevo problemi con più percorsi 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"

E l'ho messo nel mio ~ / .profile alla fine. Dato che uso BASH quasi esclusivamente, non l'ho provato in altre shell.


1
+1 per la soluzione. A proposito, rimuoverà i percorsi di duplicazione solo se stanno andando nell'elenco uno dopo l'altro. Potresti cambiare |uniqper |sort|uniqrisolvere questo problema, ma questo cambierà l'ordine di tutte le directory nel percorso che non credo sia un effetto collaterale desiderabile.
Tagar,

1

Supponendo che la tua shell sia Bash, puoi impostare il percorso con

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

ma come ha detto Levon in un'altra risposta, non appena si termina la shell le modifiche spariranno. Probabilmente vuoi impostare il tuo PATHin ~/.bash_profileo ~/.bashrc.


1

In bash puoi semplicemente $ {var / trovare / sostituire}

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

O in questo caso (poiché il bit di sostituzione è vuoto) solo:

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

Sono venuto qui per primo ma sono andato altrove perché pensavo che ci sarebbe stata un'espansione dei parametri per farlo. Più facile di sed !.

Come sostituire il carattere segnaposto o la parola nella variabile con il valore di un'altra variabile in Bash?


%significa match se alla fine della stringa, #è per l'inizio.
Sabgenton,

0

Non esistono strumenti standard per "modificare" il valore di $PATH (ovvero "aggiungi cartella solo quando non esiste già" o "rimuovi questa cartella").

Per verificare quale sarebbe il percorso alla prossima connessione, utilizzare telnet localhost(otelnet 127.0.0.1 ). Chiederà quindi il nome utente e la password.

Questo ti dà una nuova shell di login (cioè una completamente nuova che non eredita nulla dall'ambiente attuale).

Puoi controllare il valore di $PATHlì e modificare i tuoi file rc fino a quando non è corretto. Questo è utile anche per vedere se è possibile accedere nuovamente dopo aver apportato una modifica a un file importante.


Invece di dover digitare nome utente / password, basta digitare /bin/bash -i. Molto meno fastidio.
Ed Heal,

0

Come hai aggiunto questi percorsi duplicati alla tua variabile PATH? Devi aver modificato uno dei tuoi .file. ( .tcshrc, o.bashrc , ecc. a seconda del proprio sistema / shell). Il modo per risolverlo è modificare nuovamente il file e rimuovere i percorsi duplicati.

Se non hai modificato alcun file e devi aver modificato il PERCORSO in modo interattivo. In tal caso le modifiche non si "attaccheranno", ovvero se si apre un'altra shell o si esegue il logout e si accede nuovamente, le modifiche andranno automaticamente.

Nota che ci sono anche alcuni file di configurazione del sistema, ma è improbabile che tu li abbia modificati, quindi molto probabilmente cambierai i file nella tua home directory personale (se vuoi rendere permanenti quei cambiamenti una volta che ti sei sistemato su una serie di percorsi)


0

Per un semplice modello copia-incolla uso questo frammento di Perl:

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

In questo modo non è necessario sfuggire alle barre per l'operatore sostitutivo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.