Co robi $ {0% / *} w skryptach powłoki?

17

Przepraszam, jeśli to głupie pytanie, ale szukałem go bez powodzenia.

Co dokładnie robi druga linia?

#!/bin/sh
cd ${0%/*} || exit 1

Wiem, że pierwszy to shebang, drugi próbuje zmienić katalog, ale część jest myląca ${0%/*}.

Czy możesz mi wyjaśnić tę drugą linię?

Navaro
źródło
2
Jak wyjaśniono w odpowiedzi Andrei, $ {0% / *} tłumaczy się na ścieżkę katalogu poprzedzoną nazwą skryptu podczas jej wywoływania. Alternatywą jest użycie wbudowanego dirnamepolecenia typu$(dirname $0)
zawsze ucząc się
@alwayslearning: Jakiej powłoki i wersji powłoki używasz, która dirnamejest wbudowana? Z pewnością nie ma go w Bash v4.3.11, który jest domyślną powłoką w Ubuntu Trusty.
David Foerster,
Przepraszam za zamieszanie, właśnie sprawdziłem, że dirnamenie jest to wbudowana powłoka.
alwayslearning 8.01.18

Odpowiedzi:

27

${0}jest pierwszym argumentem skryptu, tj. nazwą lub ścieżką skryptu. Jeśli uruchomić skrypt jako path/to/script.sh, a następnie ${0}będzie dokładnie taki ciąg: path/to/script.sh.

%/*Część modyfikuje wartość ${0}. Oznacza to: weź wszystkie znaki, aż /pojawi się nazwa pliku. W powyższym przykładzie ${0%/*}będzie path/to.

Możesz zobaczyć to w akcji na swojej powłoce:

$ x=path/to/script.sh
$ echo "${x%/*}"
path/to

Sh obsługuje wiele innych rodzajów „podstawiania parametrów”. Oto, na przykład, jak wziąć nazwę pliku zamiast ścieżki:

$ echo "${x##*/}"
script.sh

Ogólnie rzecz biorąc, %i %%usuwaj sufiksy, podczas gdy #i ##usuwaj prefiksy. Możesz przeczytać więcej o podstawianiu parametrów .

Andrea Corbellini
źródło
2
Wydaje się, że to „|| wyjście 1” jest niepotrzebne: czy nie będzie można zmienić dir $? wynosi 1.
Josef Klimuk
2
Warto wspomnieć, że konstrukcja jest udokumentowana w instrukcji jako „Usuń pasujący wzorzec prefiksu / sufiksu”. Również dobrym sposobem na zapamiętanie, co jest tym, że # to shift 3 (na lewo od $),% to shift 5 (na prawo od $), przynajmniej na klawiaturze amerykańskiej.
chexum
1
@JosefKlimuk: || exit 1 może być potrzebny, ponieważ cdmoże wyjść ze statusem 2, a nie 1, w przypadku błędu. Zgadzam się jednak, że nie jest to bardzo przydatne (zwykle programy nie dbają o określone statusy wyjścia). Prawdopodobnie jest to część większego skryptu?
Andrea Corbellini,
1
@AndreaCorbellini Na pewno racja. Prawie jedynym sposobem, w jaki może być użyteczny, jest część większego skryptu. Skrypt, który właśnie zmienia bieżący katalog, nie ma żadnego wpływu, ponieważ wpływa tylko na powłokę uruchamiającą ten skrypt. Proces nadrzędny nigdy go nie widzi.
hvd