Warum enthält dieses Shell-Skript umgekehrte Schrägstriche?

21

In meiner Kopie des conda.shSkripts sehe ich die folgenden Zeilen:

if [ -n "${_CE_CONDA}" ] && [ -n "${WINDIR+x}" ]; then
    SYSP=$(\dirname "${CONDA_EXE}")
else
    SYSP=$(\dirname "${CONDA_EXE}")
    SYSP=$(\dirname "${SYSP}")
fi

Ich bin gespannt, warum es einen Backslash vor dem dIn gibt dirname. Ich glaube nicht, dass es notwendig ist. Diese Verwendung von Backslashes wird auch an anderen Stellen in der Quelldatei angezeigt. Gibt es dafür einen Grund, den ich vermisse?

extremeaxe5
quelle

Antworten:

30

Backslash unterdrückt die Alias-Erweiterung, dh es wird der ursprüngliche Befehl ausgeführt und sichergestellt, dass die Alias-Version nicht ausgeführt wird. Skripte können unwissentlich mit Alias-Erweiterung ausgeführt werden, wenn das System dies eingestellt hat shopt -s expand_aliases(nur BASH) oder wenn es mit ausgeführt wird source.

./conda.sh          # usually no alias expansion (unless `shopt -s expand_aliases` in BASH)
source ./conda.sh   # alias expansion
. ./conda.sh        # alias expansion

Einige Sysadmins setzen gerne einen Backslash in alles ein, um die Nebenwirkungen von Aliasnamen zu verhindern, für den Fall, dass sie ungewollt an einer anderen Stelle als Alias ​​verwendet wurden und der Alias ​​wie oben beschrieben erweitert wird. Wenn das System dies beispielsweise alias dirname='dirname -z'irgendwo festgelegt hat und die Bedingung das Erweitern des Alias ​​zulässt, ruft ein Skript, das versucht, dirname aufzurufen dirname -z, leider stattdessen auf, was nicht das beabsichtigte Skript war.

Wenn es Gewissheit gibt, dass ein solcher Alias ​​nicht existiert, können wir den gesamten Backslash entfernen und es sollte gut funktionieren.

Alternativ kann commandanstelle eines Backslashs ein Alias ​​unterdrückt werden. So kann man stattdessen \dirnameverwenden command dirname, was lesbarer aussehen könnte. (Für eingebaute Befehle wie cdsollte man builtinstattdessen verwenden). Ich bevorzuge dies stattdessen, da es auch die Funktion mit dem gleichen Namen sowie alle Aliase umgeht.

otter.pro
quelle
1
Bemerkenswert ist auch unalias -a, dass alle Aliase entfernt werden.
Centimane
19
@ Centimane Ja, aber stellen Sie sicher, dass Sie \unalias -adie Alias-Erweiterung unterdrücken
Ben C
Könnte der Sysadmin auch geschrieben haben /usr/bin/dirname?
RonJohn
@ RonJohn Ja er könnte in diesem speziellen Fall haben. Für einige Programme werden sie jedoch von verschiedenen Distributionen in verschiedene Verzeichnisse gestellt. Eine mir in den Sinn kommende Instanz ist /bin/edUbuntu vs. /usr/bin/edCentOS. Wenn Sie einen vollständigen Pfad eingeben, ist das Skript weniger portabel.
doneal24
@ doneal24 was ist mit sowas DIRNAME=$(which dirname), da whichsieht man keine aliasnamen?
RonJohn
20

Wenn conda.shes sich um eine Datei handelt, die als Quelle dient, dienen die umgekehrten Schrägstriche zum Umgehen von Aliasen. Bash deaktiviert normalerweise die Alias-Erweiterung für die Skriptausführung. Bei Quelldateien, die möglicherweise in interaktiven Shells ausgeführt werden, ist dies jedoch nicht der Fall. Es kann also nur dirnameein Alias ​​mit dem Namen ausgeführt werden dirname, \dirnamedie Aliaserweiterung wird jedoch übersprungen und eine Funktion oder ein Befehl mit dem Namen ausgeführt dirname. (Nicht nur Backslashes, sondern auch Zitate.)

muru
quelle
5
Oder command dirname.
Kusalananda
7
( \command dirnameNur für den Fall, dass jemand auch einen Alias ​​erstellt hat command.): |
muru
Warum werden Aliase umgangen? Handelt es sich bei dieser Funktionalität um einen Sonderfall oder musste sie in Bash (dh einen Hack) fest codiert werden?
extremeaxe5
@ extremeaxe5 bash führt keine Alias-Erweiterung durch, wenn (ein Teil des) Wortes in Anführungszeichen steht.
muru
1
@ extremeaxe5 wenn du fragst, warum das Feature überhaupt existiert, weiß ich nicht. Im POSIX-Standard heißt es jedoch: "Das Befehlsnamenwort [...] muss geprüft werden, um festzustellen, ob es sich um einen nicht
zitierten