Zmienna $ 0 zawiera informacje o ścieżce skryptu.
- Jak mogę zmienić informacje o ścieżce na ścieżkę bezwzględną? Mam na myśli, jak przetwarzać ~,., .. lub podobny?
- Jak mogę podzielić informacje o ścieżce na katalog i nazwę pliku?
Mogę do tego użyć Pythona / Perla, ale jeśli to możliwe, chcę użyć bash.
Odpowiedzi:
Nie musisz przetwarzać takich rzeczy, jak
~
powłoka, robi to za Ciebie. Dlatego możesz przejść~/filename
do dowolnego skryptu lub programu i to działa - wszystkie te programy nie radzą~
sobie same, twoja powłoka konwertuje argument/home/username/filename
i przekazuje go do programu:Jeśli potrzebujesz kanonicznej nazwy pliku (takiej, która nie zawiera rzeczy takich jak
..
), użyjrealpath
(dzięki Neil ):Aby podzielić ścieżkę na nazwę katalogu i nazwę pliku, użyj
dirname
ibasename
:źródło
realpath
jest lepszy, alereadlink
wydaje się, że działa, gdy go wypróbuję; znasz przykład, w którym zawodzi?cd /tmp; touch foo; ln -s foo bar; cd; readlink /tmp/bar
. To zwracafoo
irealpath
zwraca/tmp/foo
, i to jest to, czego chcesz.readlink -f
(uwaga-f
) jest prawie równoważnerealpath
i bardziej przenośne:readlink -f
w jądrach GNU i istnieje również w kilku innych systemach;realpath
jest pakowany osobno i może nie zostać zainstalowany (np. w Ubuntu 10.04 lub Debian Lenny zależy od niego tylko 5 nietypowych pakietów).Używanie dirname i basename jak wspomniane przez Michaela powinno być najbezpieczniejszym sposobem na zdobycie tego, czego chcesz.
W każdym razie, jeśli naprawdę chcesz to zrobić za pomocą „tylko narzędzi bash”, możesz użyć podstawiania parametrów:
Ten przykład pochodzi bezpośrednio z Advanced Bash Scripting Guide, który jest wart obejrzenia.
Wyjaśnienie jest dość proste:
Spójrz na ten wzorzec jak jakieś wyrażenie regularne i /
#
lub##
jak jakiś chciwy / niechciany modyfikator.Może się to przydać, jeśli będziesz musiał wykonać bardziej skomplikowane wypakowanie części ścieżki.
źródło
${...##...}
i znajomych, a niedirname
ibasename
że nie działają we wszystkich przypadkach. Na przykład zarówno${0##*/}
i${0%/*}
rozwinąć do tego samego,$0
jakby$0
nie zawierało/
.${0%/*}
nie jest dobrą alternatywą dladirname
. Ale co jest złego w używaniu${0##*/}
zamiastbasename
?$0
nazwa katalogu ma końcowy/
. Ale żałuję mojej rady, ponieważdirname
nie ma nic lepszego.realpath
to polecenie, które mówi prawdziwą ścieżkę (usuwa ... i dowiązania symboliczne itp.)Jest to standard w FreeBSD. Według tej dyskusji jest on również dostępny dla systemu Linux:
http://www.unix.com/shell-programming-scripting/89294-geting-real-path.html
Ta dyskusja oferuje również bash:
źródło