it-swarm.com.de

Wie füge ich einen Pfad korrekt zu PATH hinzu?

Ich frage mich, wo der Umgebungsvariablen PATH ein neuer Pfad hinzugefügt werden muss. Ich weiß, dass dies durch Bearbeiten von .bashrc (Zum Beispiel) erreicht werden kann, aber es ist nicht klar, wie dies zu tun ist.

Diesen Weg:

export PATH=~/opt/bin:$PATH

oder dieses?

export PATH=$PATH:~/opt/bin
994
Paolo

Das einfache Zeug

PATH=$PATH:~/opt/bin

oder

PATH=~/opt/bin:$PATH

abhängig davon, ob Sie ~/opt/bin am Ende (nach allen anderen Verzeichnissen durchsucht werden, falls sich ein Programm mit demselben Namen in mehreren Verzeichnissen befindet) oder am Anfang (vor allen anderen Verzeichnissen durchsuchen möchten) hinzufügen möchten Verzeichnisse).

Sie können mehrere Einträge gleichzeitig hinzufügen. PATH=$PATH:~/opt/bin:~/opt/node/bin Oder Variationen der Bestellung funktionieren einwandfrei. Setzen Sie export nicht an den Anfang der Zeile, da dies zusätzliche Komplikationen mit sich bringt (siehe unten unter „Hinweise zu anderen Shells als Bash“).

Wenn Ihr PATH von vielen verschiedenen Komponenten erstellt wird, erhalten Sie möglicherweise doppelte Einträge. Siehe Hinzufügen eines von Unix zu erkennenden Ausgangsverzeichnispfads, welcher Befehl? und Entfernen doppelter $ PATH-Einträge mit dem Befehl awk , um das Hinzufügen von Duplikaten zu vermeiden oder diese zu entfernen.

Einige Distributionen setzen übrigens automatisch ~/bin In Ihren PATH, falls vorhanden.

Wo soll ich es hinstellen?

Setzen Sie die Zeile zum Ändern von PATH in ~/.profile Oder in ~/.bash_profile, Wenn Sie dies haben.

Beachten Sie, dass ~/.bash_rc Von keinem Programm gelesen wird und ~/.bashrc Die Konfigurationsdatei interaktiver Bash-Instanzen ist. Sie sollten keine Umgebungsvariablen in ~/.bashrc Definieren. Der richtige Ort, um Umgebungsvariablen wie PATH zu definieren, ist ~/.profile (Oder ~/.bash_profile, Wenn Sie sich nicht für andere Shells als bash interessieren). Siehe Was ist der Unterschied zwischen ihnen und welchen soll ich verwenden?

Fügen Sie es nicht in /etc/environment Oder ~/.pam_environment Ein: Dies sind keine Shell-Dateien. Sie können dort keine Ersetzungen wie $PATH Verwenden. In diesen Dateien können Sie nur eine Variable überschreiben, nicht hinzufügen.

Mögliche Komplikationen bei einigen Systemskripten

Sie benötigen export nicht, wenn sich die Variable bereits in der Umgebung befindet: Jede Änderung des Werts der Variablen spiegelt sich in der Umgebung wider.¹ PATH befindet sich so gut wie immer in der Umgebung. Alle Unix-Systeme setzen es sehr früh (normalerweise im allerersten Prozess).

Zum Zeitpunkt der Anmeldung können Sie sich darauf verlassen, dass PATH bereits in der Umgebung vorhanden ist und bereits einige Systemverzeichnisse enthält. Wenn Sie ein Skript schreiben, das möglicherweise frühzeitig ausgeführt wird, während Sie eine virtuelle Umgebung einrichten, müssen Sie möglicherweise sicherstellen, dass PATH nicht leer ist und exportiert wird: Wenn PATH noch nicht festgelegt ist , dann würde so etwas wie PATH=$PATH:/some/directoryPATH auf :/some/directory setzen, und die leere Komponente am Anfang bedeutet das aktuelle Verzeichnis (wie .:/some/directory).

if [ -z "${PATH-}" ]; then export PATH=/usr/local/bin:/usr/bin:/bin; fi

Hinweise zu anderen Muscheln als Bash

In bash, ksh und zsh ist export eine spezielle Syntax, und sowohl PATH=~/opt/bin:$PATH Als auch export PATH=~/opt/bin:$PATH Tun sogar das Richtige. In anderen Bourne/POSIX-Shells wie dash (was auf vielen Systemen /bin/sh Ist) wird export als gewöhnlicher Befehl analysiert, was zwei Unterschiede impliziert:

Also in Muscheln wie Dash, export PATH=~/opt/bin:$PATH setzt PATH auf die Literalzeichenfolge ~/opt/bin/:, gefolgt vom Wert von PATH bis zum ersten Leerzeichen. PATH=~/opt/bin:$PATH (Eine bloße Aufgabe) erfordert keine Anführungszeichen und macht das Richtige. Wenn Sie export in einem portablen Skript verwenden möchten, müssen Sie export PATH="$HOME/opt/bin:$PATH" Oder PATH=~/opt/bin:$PATH; export PATH (Oder PATH=$HOME/opt/bin:$PATH; export PATH Schreiben, um diese auch auf die Bourne Shell zu übertragen hat export var=value nicht akzeptiert und keine Tilde-Erweiterung durchgeführt).

¹ Dies war bei Bourne-Shells nicht der Fall (wie bei der eigentlichen Bourne-Shell, nicht bei modernen POSIX-Shells), aber es ist heutzutage sehr unwahrscheinlich, dass Sie auf solche alten Shells stoßen.

So oder so funktioniert es, aber sie tun nicht dasselbe: Die Elemente von PATH werden von links nach rechts überprüft. In Ihrem ersten Beispiel haben ausführbare Dateien in ~/opt/bin Vorrang vor den in /usr/bin installierten Dateien, die möglicherweise Ihren Wünschen entsprechen oder nicht.

Insbesondere aus Sicherheitsgründen ist es gefährlich, Pfade nach vorne hinzuzufügen, da jemand, der Schreibzugriff auf Ihr ~/opt/bin erhalten kann, beispielsweise ein anderes ls einfügen kann. dort drin, die Sie dann wahrscheinlich anstelle von /bin/ls verwenden würden, ohne es zu merken. Stellen Sie sich nun dasselbe für ssh oder Ihren Browser oder Ihre Auswahl vor ... (Dasselbe gilt dreifach für das Einfügen von. In Ihren Pfad.)

88
Ulrich Schwarz

Ich bin verwirrt von Frage 2 (da sie aus der Frage entfernt wurde, da sie auf ein nicht verwandtes Problem zurückzuführen war):

Was ist eine praktikable Methode, um mehr Pfade an verschiedene Zeilen anzuhängen? Anfangs dachte ich, das könnte den Trick machen:

export PATH=$PATH:~/opt/bin
export PATH=$PATH:~/opt/node/bin

aber nicht, weil die zweite Aufgabe nicht nur ~/opt/node/bin, aber auch das gesamte zuvor zugewiesene PATH.

Dies ist eine mögliche Problemumgehung:

export PATH=$PATH:~/opt/bin:~/opt/node/bin

aus Gründen der Lesbarkeit würde ich lieber eine Zuordnung für einen Pfad haben.

Wenn du sagst

PATH=~/opt/bin

das ist all das wird in deinem PFAD sein. PATH ist nur eine Umgebungsvariable. Wenn Sie PATH hinzufügen möchten, müssen Sie die Variable mit genau dem gewünschten Inhalt neu erstellen. Das heißt, was Sie als Beispiel für Frage 2 geben, ist genau das, was Sie tun möchten, es sei denn, ich verpasse den Punkt der Frage völlig.

Ich verwende beide Formulare in meinem Code. Ich habe ein generisches Profil, das ich auf jedem Computer installiere, auf dem ich arbeite. Es sieht folgendermaßen aus, um potenziell fehlende Verzeichnisse zu berücksichtigen:

export PATH=/opt/bin:/usr/local/bin:/usr/contrib/bin:/bin:/usr/bin:/usr/sbin:/usr/bin/X11
# add optional items to the path
for bindir in $HOME/local/bin $HOME/bin; do
    if [ -d $bindir ]; then
        PATH=$PATH:${bindir}
    fi
done
39
Carl Cravens

Linux bestimmt den ausführbaren Suchpfad mit der Umgebungsvariablen $PATH. Verwenden Sie Folgendes, um das Verzeichnis/data/myscripts am Anfang der Umgebungsvariablen $PATH Hinzuzufügen:

PATH=/data/myscripts:$PATH

Verwenden Sie den folgenden Befehl, um dieses Verzeichnis am Ende des Pfads hinzuzufügen:

PATH=$PATH:/data/myscripts

Die vorhergehenden sind jedoch nicht ausreichend, da diese Änderung nur innerhalb des Skripts wirksam wird, wenn Sie eine Umgebungsvariable in einem Skript festlegen. Es gibt nur zwei Möglichkeiten, um diese Einschränkung zu umgehen:

  • Wenn Sie innerhalb des Skripts die Umgebungsvariable exportieren, ist sie in allen vom Skript aufgerufenen Programmen wirksam. Beachten Sie, dass es in dem Programm, das das Skript aufgerufen hat, nicht wirksam ist.
  • Wenn das Programm, das das Skript aufruft, dies durch Einschließen statt Aufrufen tut, werden alle Umgebungsänderungen im Skript innerhalb des aufrufenden Programms wirksam. Eine solche Aufnahme kann mit dem Punktbefehl oder dem Quellbefehl erfolgen.

Beispiele:

$HOME/myscript.sh
source $HOME/myscript.sh

Die Aufnahme enthält im Wesentlichen das "aufgerufene" Skript im "aufrufenden" Skript. Es ist wie ein #include in C. Es ist also innerhalb des "aufrufenden" Skripts oder Programms wirksam. Aber natürlich ist es in keinem Programm oder Skript, das vom aufrufenden Programm aufgerufen wird, wirksam. Um es in der gesamten Aufrufkette wirksam zu machen, müssen Sie der Einstellung der Umgebungsvariablen mit einem Exportbefehl folgen.

Das Bash-Shell-Programm enthält beispielsweise den Inhalt der Datei .bash_profile durch Aufnahme. Fügen Sie die folgenden 2 Zeilen in .bash_profile ein:

PATH=$PATH:/data/myscripts
export PATH

fügt diese 2 Codezeilen effektiv in das Bash-Programm ein. Innerhalb von bash enthält die Variable $ PATH also $HOME/myscript.sh, Und aufgrund der Exportanweisung haben alle von bash aufgerufenen Programme die geänderte Variable $PATH. Und da alle Programme, die Sie über eine Bash-Eingabeaufforderung ausführen, von Bash aufgerufen werden, gilt der neue Pfad für alles, was Sie über die Bash-Eingabeaufforderung ausführen.

Um dem Pfad ein neues Verzeichnis hinzuzufügen, müssen Sie das Verzeichnis an die Umgebungsvariable $ PATH in einem in der Shell enthaltenen Skript anhängen oder voranstellen und die Umgebungsvariable $PATH Exportieren.

Weitere Informationen hier

25
Steve Brown

Seit einiger Zeit habe ich zwei Funktionen pathadd und pathrm bei mir, die beim Hinzufügen von Elementen zum Pfad helfen, ohne sich um Duplikate kümmern zu müssen.

pathadd verwendet ein einzelnes Pfadargument und ein optionales after Argument, das, falls angegeben, an das PATH angehängt wird, andernfalls wird es vorangestellt.

In fast jeder Situation, in der Sie dem Pfad hinzufügen, möchten Sie wahrscheinlich alles überschreiben, was sich bereits im Pfad befindet. Aus diesem Grund möchte ich standardmäßig voranstellen.

pathadd() {
    newelement=${1%/}
    if [ -d "$1" ] && ! echo $PATH | grep -E -q "(^|:)$newelement($|:)" ; then
        if [ "$2" = "after" ] ; then
            PATH="$PATH:$newelement"
        else
            PATH="$newelement:$PATH"
        fi
    fi
}

pathrm() {
    PATH="$(echo $PATH | sed -e "s;\(^\|:\)${1%/}\(:\|\$\);\1\2;g" -e 's;^:\|:$;;g' -e 's;::;:;g')"
}

Fügen Sie diese in ein beliebiges Skript ein, mit dem Sie die PATH-Umgebung ändern möchten, und Sie können dies jetzt tun.

pathadd "/foo/bar"
pathadd "/baz/bat" after
export PATH

Sie werden dem Pfad garantiert nichts hinzufügen, wenn er bereits vorhanden ist. Wenn Sie jetzt sicherstellen möchten, dass /baz/bat ist am Anfang.

pathrm "/baz/bat"
pathadd "/baz/bat"
export PATH

Jetzt kann jeder Pfad nach vorne verschoben werden, wenn er sich bereits im Pfad befindet, ohne ihn zu verdoppeln.

20
Brett Ryan

Ich kann nicht für andere Distributionen sprechen, aber Ubuntu hat eine Datei/etc/environment, die der Standardsuchpfad für alle Benutzer ist. Da mein Computer nur von mir verwendet wird, füge ich dort alle gewünschten Verzeichnisse in meinen Pfad ein, es sei denn, es handelt sich um eine vorübergehende Ergänzung, die ich in ein Skript eingefügt habe.

10
Jim Bradley

Es gibt einige Situationen, in denen PATH=/a/b:$PATH kann als "falsche" Methode zum Hinzufügen eines Pfads zu PATH angesehen werden:

  1. Hinzufügen eines Pfads, der eigentlich kein Verzeichnis ist.
  2. Hinzufügen eines Pfads, der sich bereits in PATH befindet, in derselben Form.
  3. Hinzufügen eines relativen Pfads (da sich das tatsächlich durchsuchte Verzeichnis ändern würde, wenn Sie das aktuelle Arbeitsverzeichnis ändern).
  4. Hinzufügen eines Pfads, der sich bereits in PATH befindet, in einer anderen Form (d. H. Einem Alias ​​aufgrund der Verwendung von Symlinks oder ..).
  5. Wenn Sie 4 vermeiden, verschieben Sie den Pfad nicht an die Vorderseite von PATH, wenn andere Einträge in PATH überschrieben werden sollen.

Diese (nur Bash) Funktion macht in den oben genannten Situationen das "Richtige" (mit Ausnahme, siehe unten), gibt Fehlercodes zurück und druckt nette Nachrichten für Menschen. Die Fehlercodes und Meldungen können deaktiviert werden, wenn sie nicht gewünscht werden.

prepath() {
    local usage="\
Usage: prepath [-f] [-n] [-q] DIR
  -f Force dir to front of path even if already in path
  -n Nonexistent dirs do not return error status
  -q Quiet mode"

    local tofront=false errcode=1 qecho=echo
    while true; do case "$1" in
        -f)     tofront=true;       shift;;
        -n)     errcode=0;          shift;;
        -q)     qecho=':';          shift;;
        *)      break;;
    esac; done
    # Bad params always produce message and error code
    [[ -z $1 ]] && { echo 1>&2 "$usage"; return 1; }

    [[ -d $1 ]] || { $qecho 1>&2 "$1 is not a directory."; return $errcode; }
    dir="$(command cd "$1"; pwd -P)"
    if [[ :$PATH: =~ :$dir: ]]; then
        $tofront || { $qecho 1>&2 "$dir already in path."; return 0; }
        PATH="${PATH#$dir:}"        # remove if at start
        PATH="${PATH%:$dir}"        # remove if at end
        PATH="${PATH//:$dir:/:}"    # remove if in middle
    fi
    PATH="$dir:$PATH"
}

Die Ausnahme besteht darin, dass diese Funktion Pfade, die PATH hinzugefügt wurden, nicht auf andere Weise kanonisiert. Wenn sich also ein nicht-kanonischer Alias ​​für einen Pfad in PATH befindet, wird ein Duplikat hinzugefügt. Der Versuch, bereits in PATH vorhandene Pfade zu kanonisieren, ist eine heikle Angelegenheit, da ein relativer Pfad eine offensichtliche Bedeutung hat, wenn er an prepath übergeben wird. Wenn Sie sich jedoch bereits im Pfad befinden, wissen Sie nicht, wie das aktuelle Arbeitsverzeichnis lautet als es hinzugefügt wurde.

7
cjs

So fügen Sie der Umgebungsvariablen PATH einen neuen Pfad hinzu:

export PATH=$PATH:/new-path/

Damit diese Änderung auf jede von Ihnen geöffnete Shell angewendet wird, fügen Sie sie der Datei hinzu, die die Shell beim Aufrufen Quelle wird. In verschiedenen Schalen kann dies sein:

  • Bash Shell: ~/.bash_profile, ~/.bashrc oder Profil
  • Korn Shell: ~/.kshrc oder .profile
  • Z-Shell: ~/.zshrc oder .zprofile

z.B.

# export PATH=$PATH:/root/learning/bin/
# source ~/.bashrc
# echo $PATH

Sie können den angegebenen Pfad in der obigen Ausgabe sehen.

7
Amit24x7

Für mich (unter Mac OS X 10.9.5) hat das Hinzufügen des Pfadnamens (z. B. /mypathname) Zur Datei /etc/paths Sehr gut funktioniert.

Vor dem Bearbeiten gibt echo $PATH Folgendes zurück:

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

Nach dem Bearbeiten von /etc/paths Und dem Neustarten der Shell wird die Variable $ PATH an /pathname Angehängt. In der Tat gibt echo $PATH Zurück:

/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/mypathname

Was passiert ist, ist, dass /mypathname An die Variable $PATH Angehängt wurde.

6
faelx

Hier ist meine Lösung:

PATH=$(echo -n $PATH | awk -v RS=: -v ORS=: '!x[$0]++' | sed "s/\(.*\).\{1\}/\1/")

Ein schöner einfacher Einzeiler, der keine Nachlaufspuren hinterlässt :

5
AJ.