Entfernen Sie redundante Pfade aus der Variablen $ PATH

125

Ich habe den gleichen Pfad in der Variablen $ PATH 6 Mal definiert.

Ich habe mich nicht abgemeldet, um zu überprüfen, ob es funktioniert hat.

Wie kann ich die Duplikate entfernen?

Die Variable $ PATH sieht folgendermaßen aus:

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

Wie würde ich es auf einfach zurücksetzen

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
Charles Henry
quelle
wo hast du es 6 mal definiert in welchen Dateien?
Hovanessyan
3
Mögliches Duplikat von Was ist die eleganteste Methode, um einen Pfad aus der Variablen $ PATH in Bash zu entfernen?
Ciro Santilli 17 冠状 病 六四 事件 17

Antworten:

122

Sie führen einfach aus:

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

Dies gilt für die aktuelle Sitzung, wenn Sie sie dauerhaft ändern möchten. Fügen Sie sie zu einem beliebigen .bashrc-, bash.bashrc- / / etc / -Profil hinzu - je nachdem, was Ihrem System und den Benutzeranforderungen entspricht.

Hinweis: Dies ist für Linux. Wir werden dies für neue Programmierer klar machen. (`, ') Versuchen Sie nicht, SET = this.

hovanessyan
quelle
Ja, ich habe sie dauerhaft in bash.bashrc gesetzt. Sollte der Befehl also so etwas sein? echo 'export PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games' >> ~/.bashrc
Charles Hendry
Die Sache ist, dass abhängig von Ihrem Betriebssystem eine Reihe von Konfigurationen ausgeführt wird. Sie müssen sicherstellen, dass die Variable PATH später nicht überschrieben wird. Der einfachste Weg, dies zu tun (für einen Benutzer), besteht darin, es in der persönlichen .bashrc des Benutzers zu überschreiben, die sich normalerweise in seinem Home-Verzeichnis befindet.
Hovanessyan
1
Ihr Befehl setzt den PATH auf - $ PATH (den aktuellen Wert von PATH) + den String / usr / local / sbin: / usr / local / bin: / usr / sbin: / usr / bin: / sbin: / bin: / usr / gam‌ es. Wenn Sie nur den String haben möchten, entfernen Sie $ PATH + das Semikolon (:) aus Ihrem Befehl. Es spielt keine Rolle, ob Sie echo verwenden oder die Datei ~ / .bashrc von Hand bearbeiten.
Hovanessyan
Die Datei bash.bashrc befindet sich im Ordner / etc. Die Variable $ PATH wird jedoch nicht angezeigt, daher bin ich mir nicht sicher, wo ich sie bearbeiten soll
Charles Hendry,
In Ihrem ersten Kommentar wiederholen Sie ~ / .bashrc (zitiert: >> ~ / .bashrc), nicht /etc/bash.bashrc. Wenn Sie den PFAD für einen bestimmten Benutzer ändern möchten, bearbeiten Sie ihn in der Datei / home / <Name des Benutzers> /. Bashrc. Die Datei /etc/bash.bashrc gilt für alle Benutzer.
Hovanessyan
70

Wenn Sie Bash verwenden, können Sie auch Folgendes tun, wenn Sie beispielsweise das Verzeichnis /home/wrong/dir/aus Ihrer PATHVariablen entfernen möchten :

PATH=`echo $PATH | sed -e 's/:\/home\/wrong\/dir\/$//'`
Sufinawaz
quelle
1
Dies war nützlich für mich, da in / etc / profile ein Verzeichnis hinzugefügt wurde, das ich ausschließen wollte, aber keinen Schreibzugriff auf / etc. Habe. Danke :)
Samizdis
13
Protip: Sie können verschiedene Deliminatoren im sed-Ausdruck verwenden, um das Entkommen zu vermeiden:PATH=$(echo $PATH | sed -e 's|:/home/wrong/dir|$||')
iNecas
4
Dieser Trick hilft, wenn ich sofort einen neuen PATH haben möchte und mich nicht vom aktuellen Terminal abmelden möchte. Um jedoch ein Durcheinander zu vermeiden, sollte man mit dem PATH-Generierungsbefehl (dh echo $PATH | sed -e 's/:\/home\/wrong\/dir\/$//') experimentieren, bevor man ihn PATH zuweist.
Biocyberman
2
Dies funktioniert nicht, wenn der zu löschende Pfad der erste Pfad in ist $PATH. Verwenden Sie diese:PATH=$(echo :$PATH: | sed -e 's,:/home/wrong/dir:,:,g' -e 's/^://' -e 's/:$//')
Robin Hsu
hat nicht funktioniert $ PATH=echo $ PATH | sed -es /: \ / kratzer \ / sjn \ / anaconda \ / bin \ / python \ / $ // '`` zum entfernen von / kratzer / sjn / anaconda / bin / python
Mona Jalal
13

Linux: Entfernen Sie redundante Pfade aus der Variablen $ PATH

Linux From Scratch hat diese Funktion 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"
}

Dies soll mit diesen Funktionen zum Hinzufügen zum Pfad verwendet werden, damit Sie dies nicht redundant tun:

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

Die einfache Verwendung besteht darin, nur pathremoveden zu entfernenden Verzeichnispfad anzugeben. Beachten Sie jedoch, dass dieser genau übereinstimmen muss:

$ pathremove /home/username/anaconda3/bin

Dadurch wird jede Instanz dieses Verzeichnisses aus Ihrem Pfad entfernt.

Wenn Sie das Verzeichnis in Ihrem Pfad haben möchten, aber ohne Redundanzen, können Sie einfach eine der anderen Funktionen verwenden, z. B. - für Ihren speziellen Fall:

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

Aber wenn es nicht um Lesbarkeit geht, ist es an dieser Stelle besser, nur Folgendes zu tun:

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

Würde das oben genannte in allen dem Menschen bekannten Schalen funktionieren?

Ich würde das oben zur Arbeit in anmaßen sh, dashund bashzumindest. Ich wäre überrascht zu erfahren, dass es nicht funktioniert csh, fish', orksh`. Ich bezweifle, dass es in Windows Command Shell oder Powershell funktionieren würde.

Wenn Sie über Python verfügen, sollte der folgende Befehl die direkt angeforderten Anweisungen ausführen (dh redundante Pfade entfernen):

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

Ein Einzeiler (um mehrzeilige Probleme zu umgehen):

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

Das Obige entfernt später redundante Pfade. Um frühere redundante Pfade zu entfernen, verwenden Sie den Index einer umgekehrten Liste und kehren Sie ihn erneut um:

$ PATH=$( python -c "
import os
path = os.environ['PATH'].split(':')[::-1]
print(':'.join(sorted(set(path), key=path.index, reverse=True)))
" )
Aaron Hall
quelle
+1. funktioniert pathremove () in allen Shell-Varianten wie csh, ksh, bash usw.? Übrigens hat mein / etc / profile auf RHEL nicht partremove (), sondern nur pathmunge ().
Tagar
1
@Tagar Ich übernehme keine Garantie für die Kompatibilität mit allen anderen Shells. Ich schlage vor, es auf der von Ihnen verwendeten Shell zu testen. Wenn es für Ihre Shell nicht funktioniert, können Sie Python verwenden, wenn Sie es installiert haben. Ich habe der Antwort etwas Python hinzugefügt, um zu beschreiben, wie.
Aaron Hall
Wenn ich "3.5.3 Shell Parameter Expansion" richtig gelesen habe, ${!PATHVARIABLE}ist dies eine Art variable Indirektion, aber ich bin mir nicht sicher, wie es hier funktioniert. Könnten Sie es bitte erklären?
Loxaxs
@loxaxs Dies ist eine lokale Variable in diesen Bash-Funktionen, die mit dem integrierten localElement deklariert wurde (die nur innerhalb einer Funktion verwendet werden kann). Wenn Sie weitere Fragen haben, sollten Sie wahrscheinlich eine neue Frage auf der Site stellen (nachdem Sie zuerst danach gesucht haben, um dies sicherzustellen Sie erstellen kein genaues Duplikat ...).
Aaron Hall
Dies ist eine wirklich interessante Antwort, danke für das Schreiben! Die ursprüngliche Frage, eine durcheinandergebrachte PATH-Variable zu bereinigen, scheint jedoch nicht elegant gelöst zu sein (obwohl ich zugeben muss, dass man bei Verwendung dieser Funktionen zunächst nicht mit einem durcheinandergebrachten PATH enden würde).
Christian Herenz
9

Hier ist ein einzeiliger Code, der den PFAD bereinigt

  • Es stört nicht die Reihenfolge des Pfads, sondern entfernt nur Duplikate
  • Leckereien: und empth PATH anmutig
  • Es werden keine Sonderzeichen verwendet, daher ist kein Escape erforderlich
  • Wird verwendet, /bin/awkdamit es auch dann funktioniert, wenn PATH fehlerhaft ist

    export PATH="$(echo "$PATH" |/bin/awk 'BEGIN{RS=":";}
    {sub(sprintf("%c$",10),"");if(A[$0]){}else{A[$0]=1;
    printf(((NR==1)?"":":")$0)}}')";
GreenFox
quelle
1
hat es jemand getestet? ist sicher?
Joe RR
2
Wenn Sie awk nicht installiert haben, wird Ihr Pfad bereinigt. Ich empfehle, Ihren Pfad zuvor mit echo $ PATH
Jose Pita am
Funktioniert bei mir nicht ... Ich habe awk installiert, aber einige Duplikate werden nicht entfernt.
Christian Herenz
3
  1. Gerade echo $PATH
  2. Kopieren Sie Details in einen Texteditor
  3. unerwünschte Einträge entfernen
  4. PATH= # pass new list of entries
mrwagaba
quelle
2

Wenn Sie nur doppelte Pfade entfernen möchten, verwende ich dieses Skript, das ich vor einiger Zeit geschrieben habe, da ich Probleme mit mehreren perl5 / bin-Pfaden hatte:

#!/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"

Und ich habe es am Ende in mein ~ / .profil geschrieben. Da ich BASH fast ausschließlich benutze, habe ich es nicht in anderen Shells ausprobiert.

Kevin Nathan
quelle
1
+1 für die Lösung. Übrigens werden Duplizierungspfade nur entfernt, wenn sie nacheinander in die Liste aufgenommen werden. Sie können zu ändern |uniq, |sort|uniqum dies zu beheben, aber dies ändert die Reihenfolge aller Verzeichnisse im Pfad, was ich nicht für einen wünschenswerten Nebeneffekt halte.
Tagar
1

Angenommen, Ihre Shell ist Bash, können Sie den Pfad mit festlegen

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

Aber wie Levon in einer anderen Antwort sagte, werden die Änderungen verschwunden sein, sobald Sie die Shell beenden. Sie möchten wahrscheinlich Ihr PATHin ~/.bash_profileoder einrichten ~/.bashrc.

Löwe
quelle
1

In Bash können Sie einfach $ {var / find / replace}

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

Oder in diesem Fall (da das Ersetzungsbit leer ist) einfach:

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

Ich kam zuerst hierher, ging aber zu einer anderen Ware, da ich dachte, dass es eine Parametererweiterung geben würde , um dies zu tun. Einfacher als sed!.

Wie ersetze ich ein Platzhalterzeichen oder -wort in einer Variablen durch einen Wert aus einer anderen Variablen in Bash?

Sabgenton
quelle
%bedeutet Übereinstimmung, wenn am Ende der Zeichenfolge #steht, für den Anfang.
Sabgenton
0

Es gibt keine Standardwerkzeuge zum "Bearbeiten" des Werts von $PATH(dh "Ordner nur hinzufügen, wenn er noch nicht vorhanden ist" oder "Diesen Ordner entfernen").

Verwenden Sie telnet localhost(oder telnet 127.0.0.1) , um zu überprüfen, wie der Pfad beim nächsten Anmelden aussehen würde . Anschließend werden Sie nach Ihrem Benutzernamen und Passwort gefragt.

Dadurch erhalten Sie eine neue Anmeldeshell (dh eine völlig neue, die nichts von der aktuellen Umgebung erbt).

Sie können den Wert der $PATHdort überprüfen und Ihre RC-Dateien bearbeiten, bis es korrekt ist. Dies ist auch nützlich, um festzustellen, ob Sie sich nach einer Änderung an einer wichtigen Datei überhaupt wieder anmelden können.

Aaron Digulla
quelle
Anstatt den Benutzernamen / das Passwort eingeben zu müssen, geben Sie einfach ein /bin/bash -i. Viel weniger Ärger.
Ed Heal
0

Wie haben Sie diese doppelten Pfade zu Ihrer PATH-Variablen hinzugefügt? Sie müssen eine Ihrer .Dateien bearbeitet haben . ( .tcshrc, oder .bashrcusw., abhängig von Ihrem speziellen System / Ihrer Shell). Sie können das Problem beheben, indem Sie die Datei erneut bearbeiten und die doppelten Pfade entfernen.

Wenn Sie nicht bearbeiten Sie alle Dateien, und Sie müssen Sie den Pfad interaktiv geändert haben. In diesem Fall bleiben die Änderungen nicht "hängen", dh wenn Sie eine andere Shell öffnen oder sich abmelden und wieder anmelden, werden die Änderungen automatisch gelöscht.

Beachten Sie, dass es auch einige systemweite Konfigurationsdateien gibt, aber es ist unwahrscheinlich, dass Sie diese geändert haben. Daher werden Sie höchstwahrscheinlich Dateien in Ihrem persönlichen Ausgangsverzeichnis ändern (wenn Sie diese Änderungen dauerhaft vornehmen möchten, sobald Sie sich für eine Reihe von Pfaden entschieden haben).

Levon
quelle
0

Für eine einfache Vorlage zum Kopieren und Einfügen verwende ich dieses Perl-Snippet:

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

Auf diese Weise müssen Sie den Schrägstrichen für den Ersatzoperator nicht entkommen.

Alexander Shcheblikin
quelle