Dlaczego w tym skrypcie powłoki znajdują się ukośniki odwrotne?

21

W mojej kopii conda.shskryptu widzę następujące wiersze:

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

Jestem ciekaw, dlaczego istnieje odwrotny ukośnik przed The dw dirname. Nie wierzę, że jest to konieczne. Takie użycie odwrotnych ukośników pojawia się również w innych miejscach w pliku źródłowym. Czy brakuje mi takiego powodu?

extremeaxe5
źródło
2
Powiązane: Uruchom polecenie ukryte pod aliasem
steeldriver

Odpowiedzi:

30

Odwrotny ukośnik powstrzyma rozszerzenie aliasu, tj. Wykonuje oryginalne polecenie i upewnia się, że wersja aliasu nie działa. Skrypty mogą nieświadomie działać z rozszerzaniem aliasów, gdy system jest ustawiony shopt -s expand_aliases(tylko BASH) lub jeśli jest wykonywany przy użyciu source.

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

Niektórzy administratorzy lubią wstawiać ukośnik we wszystkim jako środek zapobiegawczy przeciwko efektom ubocznym aliasów, na wypadek, gdyby został przypadkowo aliasowany gdzie indziej, a alias zostanie rozwinięty, jak wyjaśniono wcześniej. Na przykład, jeśli system alias dirname='dirname -z'gdzieś to ustawił i warunek pozwala na rozwinięcie aliasu, wówczas skrypt, który próbuje wywołać dirname, niestety zadzwoni dirname -z, co nie było zamierzone.

Jeśli istnieje pewność, że taki alias nie istnieje, możemy usunąć cały ukośnik odwrotny i powinien on działać poprawnie.

Alternatywnie można użyć commandzamiast wersji z odwrotnym ukośnikiem, aby ukryć alias. Zamiast tego \dirnamemożna użyć command dirname, który może wyglądać na bardziej czytelny. (W przypadku wbudowanych poleceń, takich jak cd, należy użyć builtinzamiast tego). Wolę to zamiast tego, ponieważ omija również funkcję o tej samej nazwie, a także wszelkie aliasy.

otter.pro
źródło
1
Warto również zauważyć unalias -a, że usuwa wszystkie aliasy.
Centimane
19
@Centimane Tak, ale upewnij się, że musisz zrobić, aby \unalias -astłumić rozszerzenie aliasu
Ben C
Czy sysadmin też mógł napisać /usr/bin/dirname?
RonJohn
@RonJohn Tak, mógł mieć w tym konkretnym przypadku. Jednak w przypadku niektórych programów różne dystrybucje umieszczają je w różnych katalogach. Jednym z przykładów, które przychodzą mi na myśl, jest /bin/edUbuntu vs. /usr/bin/edCentOS. Ustawienie pełnej ścieżki powoduje, że skrypt jest mniej przenośny.
doneal24
@ doneal24 co powiesz na coś takiego DIRNAME=$(which dirname), skoro whichnie widzi aliasów?
RonJohn
20

Jeśli conda.shplik ma być pozyskiwany, to odwrotne ukośniki służą do pomijania aliasów. Bash zazwyczaj wyłącza rozszerzenie aliasu dla wykonywania skryptu, ale w przypadku plików źródłowych, które mogą działać w interaktywnych powłokach, tak nie jest. dirnameMoże więc po prostu uruchomić alias o nazwie dirname, ale \dirnamepominie rozwinięcie aliasu i uruchomi funkcję lub polecenie o nazwie dirname. (Ale nie tylko odwrotne ukośniki, wystarczy cytowanie.)

muru
źródło
5
Lub command dirname.
Kusalananda
7
( \command dirname, na wypadek, gdyby ktoś również stworzył alias command.): |
muru
Dlaczego omija aliasy? Czy ta funkcjonalność jest specjalnym przypadkiem czegoś, czy też musiała zostać zakodowana w bashu (np. Hack)?
extremeaxe5
@ extremeaxe5 bash nie rozszerza aliasu, jeśli (jakakolwiek część) słowo jest cytowane.
muru
1
@ extremeaxe5, jeśli pytasz, dlaczego ta funkcja w ogóle istnieje, nie wiem. Jest jednak w standardzie POSIX : „słowo nazwa polecenia [...] zostanie sprawdzone w celu ustalenia, czy jest to niecytowany , poprawny alias”
muru