IMO, co spowoduje zamieszanie. „Uruchomiłem foo.sh, ale to mówi, że prowadzę bar.sh !? To musi być błąd!” Poza tym jednym z celów posiadania dowiązań symbolicznych o różnych nazwach jest zapewnienie różnych funkcji opartych na nazwie, którą nazywa się jako (na niektórych platformach używaj gzip i gunzip).
1 Oznacza to, że aby rozwiązywać dowiązania symboliczne w taki sposób, że gdy użytkownik wykonuje foo.shfaktycznie dowiązanie symboliczne bar.sh, wolisz użyć rozpoznanej nazwy bar.shzamiast foo.sh.
-1, 1. readlink przenosi tylko jedno głębokie dowiązanie symboliczne, 2. $0w pierwszym przykładzie podlega $0podziałowi słów, 3. jest przekazywany do basename, readlink i echa w pozycji, która pozwala na traktowanie go jako przełącznika linii poleceń . Proponuję zamiast me=$(basename -- "$0")lub bardziej efektywnie kosztem czytelności me=${0##*/}. W przypadku dowiązań symbolicznych, me=$(basename -- "$(readlink -f -- "$0")")zakładając , że GNU utils, w przeciwnym razie będzie to bardzo długi skrypt, którego tutaj nie napiszę.
Score_Under
246
# ------------- PISMO ------------- # # ------------- WEZWANE ------ ------- ##!/bin/bash
echo
echo "# arguments called with ----> ${@} "
echo "# \$1 ----------------------> $1 "
echo "# \$2 ----------------------> $2 "
echo "# path to me ---------------> ${0} "
echo "# parent path --------------> ${0%/*} "
echo "# my name ------------------> ${0##*/} "
echo
exit
# Uwaga w następnym wierszu pierwszy argument jest wywoływany w obrębie podwójnego, # i pojedynczego cudzysłowu, ponieważ zawiera dwa słowa$ / misc / shell_scripts / check_root / show_parms . sh „„ hello there ” ” „william” ”# ------------- WYNIKI ------------- ## argumenty wywołane z ---> 'hello there' 'william' # $ 1 ----------------------> 'hello there' # $ 2 ---- ------------------> 'william' # ścieżka do mnie --------------> / misc / shell_scripts / check_root / show_parms. sh # ścieżka nadrzędna -------------> / misc / shell_scripts / check_root # moje imię -----------------> show_parms.sh# ------------- KONIEC ------------- #
Jak uzyskać po prostu show_params, tj. Nazwę bez opcjonalnego rozszerzenia?
Acumenus
Nie działa w przypadku wywołania skryptu z innego folderu. Ścieżka jest zawarta w ${0##*/}. Testowane przy użyciu GitBash.
AlikElzin-kilaka
1
Powyższe nie działało dla mnie ze skryptu .bash_login, ale rozwiązanie Dimitre Radoulov z $ BASH_SOURCE działa świetnie.
Jan
@John Na pewno masz na myśli .bash_profile ? Lub alternatywnie .bashrc ? Powinieneś jednak wiedzieć, że istnieją pewne subtelne różnice w sposobie wywoływania / pozyskiwania. Jestem bardzo zmęczony, ale jeśli dobrze się nad tym zastanowić, to prawdopodobnie problem. Jedno miejsce ma znaczenie, jeśli logujesz się zdalnie do systemu np. Ssh w porównaniu z systemem lokalnym.
Pryftan
193
Przy bash> = 3 działają następujące funkcje:
$ ./s
0 is:./s
BASH_SOURCE is:./s
$ ../s
0 is: bash
BASH_SOURCE is:./s
$ cat s
#!/bin/bash
printf '$0 is: %s\n$BASH_SOURCE is: %s\n'"$0""$BASH_SOURCE"
Ta odpowiedź to IMHO najlepsza, ponieważ rozwiązanie wykorzystuje kod samokontrujący. $ BASH_SOURCE jest całkowicie zrozumiałe bez czytania jakiejkolwiek dokumentacji, podczas gdy np. $ {0 ## * /} nie jest
Andreas M. Oberheim 6'18
Wierzę, że ta odpowiedź ma większą wartość, ponieważ jeśli działamy tak . <filename> [arguments], podamy $0nazwę powłoki wywołującej. Na pewno przynajmniej na OSX.
Mihir
68
Jeśli nazwa zawiera spacje skrypt w nim bardziej wytrzymałe sposobem jest użycie "$0"albo "$(basename "$0")"- albo na MacOS: "$(basename \"$0\")". Zapobiega to zniekształcaniu lub interpretowaniu nazwy w jakikolwiek sposób. Ogólnie dobrą praktyką jest zawsze podwójne cytowanie nazw zmiennych w powłoce.
A co, jeśli chcę bez opcjonalnego rozszerzenia pliku?
Acumenus
Aby usunąć rozszerzenie, możesz wypróbować „$ {VARIABLE% .ext}”, gdzie VARIABLE to wartość otrzymana z $ {0 ## * /}, a „.ext” to rozszerzenie, które chcesz usunąć.
BrianV
19
Aby odpowiedzieć Chrisowi Conwayowi , w Linuksie (przynajmniej) zrobiłbyś to:
echo $(basename $(readlink -nf $0))
readlink drukuje wartość dowiązania symbolicznego. Jeśli nie jest dowiązaniem symbolicznym, drukuje nazwę pliku. -n mówi, aby nie drukował nowego wiersza. -f mówi mu, aby podążał za linkiem całkowicie (jeśli dowiązanie symboliczne było linkiem do innego linku, rozwiązałoby to również).
-n jest nieszkodliwy, ale nie jest konieczny, ponieważ struktura $ (...) go przycina.
zhaorufei,
16
Przekonałem się, że ta linia zawsze działa, niezależnie od tego, czy plik jest pobierany czy uruchamiany jako skrypt.
echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
Jeśli chcesz podążać za dowiązaniami symbolicznymi, użyj readlinkścieżki powyżej, rekurencyjnie lub nierekurencyjnie.
Powód, dla którego działa jednolinijka, jest wyjaśniony przez użycie BASH_SOURCEzmiennej środowiskowej i jej powiązania FUNCNAME.
BASH_SOURCE
Zmienna tablicowa, której członkowie są źródłowymi nazwami plików, w których zdefiniowane są odpowiednie nazwy funkcji powłoki w zmiennej tablicowej FUNCNAME. Funkcja powłoki $ {FUNCNAME [$ i]} jest zdefiniowana w pliku $ {BASH_SOURCE [$ i]} i wywołana z $ {BASH_SOURCE [$ i + 1]}.
FUNCNAME
Zmienna tablicowa zawierająca nazwy wszystkich funkcji powłoki znajdujących się obecnie na stosie wywołań wykonawczych. Element o indeksie 0 jest nazwą każdej aktualnie wykonywanej funkcji powłoki. Najniższy element (ten o najwyższym indeksie) to „main”. Ta zmienna istnieje tylko podczas wykonywania funkcji powłoki. Przypisania do FUNCNAME nie działają i zwracają status błędu. Jeśli FUNCNAME jest rozbrojony, traci swoje specjalne właściwości, nawet jeśli jest następnie resetowany.
Tej zmiennej można używać z BASH_LINENO i BASH_SOURCE. Każdy element FUNCNAME ma odpowiadające elementy w BASH_LINENO i BASH_SOURCE do opisania stosu wywołań. Na przykład $ {FUNCNAME [$ i]} został wywołany z pliku $ {BASH_SOURCE [$ i + 1]} w linii $ {BASH_LINENO [$ i]}. Wbudowane narzędzie wywołujące wyświetla bieżący stos połączeń przy użyciu tych informacji.
Działa, jeśli źródło w pliku a (zakładając a, że zawartość jest echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}") z sesji interaktywnej - poda aścieżkę. Ale jeśli napiszesz skrypt bz source anim i uruchomisz ./b, zwróci on bścieżkę.
PSkocik
12
Te odpowiedzi są poprawne dla przypadków, które podają, ale nadal występuje problem, jeśli skrypt zostanie uruchomiony z innego skryptu przy użyciu słowa kluczowego „source” (tak, aby działał w tej samej powłoce). W takim przypadku otrzymasz 0 $ skryptu wywołującego. W tym przypadku nie sądzę, że można uzyskać nazwę samego skryptu.
Jest to przypadek skrajny i nie należy go traktować zbyt poważnie. Jeśli uruchomisz skrypt bezpośrednio z innego skryptu (bez „źródła”), użycie $ 0 będzie działać.
Zgadzam się, że dezorientacja dowiązań symbolicznych byłaby myląca, jeśli Twoim celem jest przekazanie informacji zwrotnej użytkownikowi, ale zdarzają się sytuacje, w których musisz uzyskać kanoniczną nazwę skryptu lub innego pliku, i to jest najlepszy sposób, imo.
To rozwiązuje dowiązania symboliczne (robi to realpath), obsługuje spacje (robią to podwójne cudzysłowy) i znajdzie bieżącą nazwę skryptu, nawet gdy jest pozyskiwany (. ./Myscript) lub wywoływany przez inne skrypty ($ BASH_SOURCE obsługuje to). Po tym wszystkim dobrze jest zapisać to w zmiennej środowiskowej do ponownego użycia lub łatwego kopiowania w innym miejscu (this =) ...
FYI realpathnie jest wbudowanym poleceniem BASH. Jest to samodzielny plik wykonywalny, który jest dostępny tylko w niektórych dystrybucjach
StvnW
4
W bashmożna uzyskać nazwę pliku skryptu za pomocą $0. Generalnie $1, $2etc są do argumentów dostęp CLI. Podobnie $0jest uzyskać dostęp do nazwy, która wyzwala skrypt (nazwa pliku skryptu).
#!/bin/bash
echo "You are running $0"......
Jeśli wywołasz skrypt ze ścieżką podobną, /path/to/script.shwówczas $0również poda nazwę pliku ze ścieżką. W takim przypadku należy użyć, $(basename $0)aby uzyskać tylko nazwę pliku skryptu.
[EDYCJA] Na @ephemient w komentarzach powyżej, chociaż łącze symboliczne może wydawać się wymyślone, można manipulować $0tak, aby nie reprezentował zasobu systemu plików. OP jest nieco niejednoznaczny co do tego, czego chciał.
dodałem odpowiedź na to pytanie do mojej powyższej odpowiedzi, ale nie zgadzam się z tym, że to jest to, czego naprawdę chcieliśmy (lub że powinieneś tego chcieć, z wyjątkiem okoliczności łagodzących, których obecnie nie mogę pojąć)
Tanktalus 10.1008
2
Wydaje mi się, że drukowanie linktoscript zamiast script.sh to funkcja, a nie błąd. Kilka poleceń uniksowych używa swojej nazwy do zmiany ich zachowania. Przykładem jest vi / ex / view.
mouviciel
@Tanktalus: Są przypadki, w których chcesz zmienić zachowanie w zależności od rzeczywistej lokalizacji pliku - w poprzednim projekcie miałem skrypt „Active branch”, który mógłby dowiązać do ścieżki kilku narzędzi z gałęzi, w której byłem pracować nad; narzędzia te mogłyby następnie dowiedzieć się, w którym katalogu zostały sprawdzone, aby uruchomić odpowiednie pliki.
Andrew Aylett,
2
Informacje dzięki Billowi Hernandezowi. Dodałem pewne preferencje, które przyjmuję.
#!/bin/bashfunctionUsage(){
echo " Usage: show_parameters [ arg1 ][ arg2 ]"}[[ ${#2}-eq 0]]&&Usage||{
echo
echo "# arguments called with ----> ${@} "
echo "# \$1 -----------------------> $1 "
echo "# \$2 -----------------------> $2 "
echo "# path to me ---------------> ${0} "| sed "s/$USER/\$USER/g"
echo "# parent path --------------> ${0%/*} "| sed "s/$USER/\$USER/g"
echo "# my name ------------------> ${0##*/} "
echo
}
export LC_ALL=en_US.UTF-8#!/bin/bash#!/bin/sh#----------------------------------------------------------------------
start_trash(){
ver="htrash.sh v0.0.4"
$TRASH_DIR # url to trash $MY_USER
$TRASH_SIZE # Show Trash Folder Size
echo "Would you like to empty Trash [y/n]?"
read ans
if[ $ans = y -o $ans = Y -o $ans = yes -o $ans =Yes-o $ans = YES ]then
echo "'yes'"
cd $TRASH_DIR && $EMPTY_TRASH
fiif[ $ans = n -o $ans = N -o $ans = no -o $ans =No-o $ans = NO ]then
echo "'no'"fireturn $TRUE
}#-----------------------------------------------------------------------
start_help(){
echo "HELP COMMANDS-----------------------------"
echo "htest www open a homepage "
echo "htest trash empty trash "return $TRUE
}#end Help#-----------------------------------------------#
homepage=""return $TRUE
}#end cpdebtemp# -Case start# if no command line arg given# set val to Unknownif[-z $1 ]then
val="*** Unknown ***"elif[-n $1 ]then# otherwise make first arg as val
val=$1
fi# use case statement to make decision for rentalcase $val in"trash") start_trash ;;"help") start_help ;;"www") firefox $homepage ;;*) echo "Sorry, I can not get a $val for you!";;esac# Case stop
Odpowiedzi:
Aby odczytać dowiązanie symboliczne 1 , które zwykle nie jest tym, czego chcesz (zwykle nie chcesz w ten sposób mylić użytkownika), spróbuj:
IMO, co spowoduje zamieszanie. „Uruchomiłem foo.sh, ale to mówi, że prowadzę bar.sh !? To musi być błąd!” Poza tym jednym z celów posiadania dowiązań symbolicznych o różnych nazwach jest zapewnienie różnych funkcji opartych na nazwie, którą nazywa się jako (na niektórych platformach używaj gzip i gunzip).
1 Oznacza to, że aby rozwiązywać dowiązania symboliczne w taki sposób, że gdy użytkownik wykonuje
foo.sh
faktycznie dowiązanie symbolicznebar.sh
, wolisz użyć rozpoznanej nazwybar.sh
zamiastfoo.sh
.źródło
$0
w pierwszym przykładzie podlega$0
podziałowi słów, 3. jest przekazywany do basename, readlink i echa w pozycji, która pozwala na traktowanie go jako przełącznika linii poleceń . Proponuję zamiastme=$(basename -- "$0")
lub bardziej efektywnie kosztem czytelnościme=${0##*/}
. W przypadku dowiązań symbolicznych,me=$(basename -- "$(readlink -f -- "$0")")
zakładając , że GNU utils, w przeciwnym razie będzie to bardzo długi skrypt, którego tutaj nie napiszę.źródło
show_params
, tj. Nazwę bez opcjonalnego rozszerzenia?${0##*/}
. Testowane przy użyciu GitBash.Przy bash> = 3 działają następujące funkcje:
źródło
dirname $BASE_SOURCE
”, aby uzyskać katalog, w którym znajdują się skrypty.$BASH_SOURCE
daje poprawną odpowiedź przy pozyskiwaniu skryptu.Obejmuje to jednak ścieżkę, więc aby uzyskać tylko nazwę pliku skryptu, użyj:
źródło
. <filename> [arguments]
, podamy$0
nazwę powłoki wywołującej. Na pewno przynajmniej na OSX.Jeśli nazwa zawiera spacje skrypt w nim bardziej wytrzymałe sposobem jest użycie
"$0"
albo"$(basename "$0")"
- albo na MacOS:"$(basename \"$0\")"
. Zapobiega to zniekształcaniu lub interpretowaniu nazwy w jakikolwiek sposób. Ogólnie dobrą praktyką jest zawsze podwójne cytowanie nazw zmiennych w powłoce.źródło
Jeśli chcesz bez ścieżki, skorzystaj
${0##*/}
źródło
Aby odpowiedzieć Chrisowi Conwayowi , w Linuksie (przynajmniej) zrobiłbyś to:
readlink drukuje wartość dowiązania symbolicznego. Jeśli nie jest dowiązaniem symbolicznym, drukuje nazwę pliku. -n mówi, aby nie drukował nowego wiersza. -f mówi mu, aby podążał za linkiem całkowicie (jeśli dowiązanie symboliczne było linkiem do innego linku, rozwiązałoby to również).
źródło
Przekonałem się, że ta linia zawsze działa, niezależnie od tego, czy plik jest pobierany czy uruchamiany jako skrypt.
Jeśli chcesz podążać za dowiązaniami symbolicznymi, użyj
readlink
ścieżki powyżej, rekurencyjnie lub nierekurencyjnie.Powód, dla którego działa jednolinijka, jest wyjaśniony przez użycie
BASH_SOURCE
zmiennej środowiskowej i jej powiązaniaFUNCNAME
.[Źródło: instrukcja Bash]
źródło
a
(zakładająca
, że zawartość jestecho "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
) z sesji interaktywnej - podaa
ścieżkę. Ale jeśli napiszesz skryptb
zsource a
nim i uruchomisz./b
, zwróci onb
ścieżkę.Te odpowiedzi są poprawne dla przypadków, które podają, ale nadal występuje problem, jeśli skrypt zostanie uruchomiony z innego skryptu przy użyciu słowa kluczowego „source” (tak, aby działał w tej samej powłoce). W takim przypadku otrzymasz 0 $ skryptu wywołującego. W tym przypadku nie sądzę, że można uzyskać nazwę samego skryptu.
Jest to przypadek skrajny i nie należy go traktować zbyt poważnie. Jeśli uruchomisz skrypt bezpośrednio z innego skryptu (bez „źródła”), użycie $ 0 będzie działać.
źródło
Ponieważ niektóre komentarze dotyczyły nazwy pliku bez rozszerzenia, oto przykład, jak to zrobić:
Cieszyć się!
źródło
Re: Odpowiedź Tanktalusa (zaakceptowana) powyżej, nieco czystszym sposobem jest użycie:
Jeśli twój skrypt pochodzi z innego skryptu bash, możesz użyć:
Zgadzam się, że dezorientacja dowiązań symbolicznych byłaby myląca, jeśli Twoim celem jest przekazanie informacji zwrotnej użytkownikowi, ale zdarzają się sytuacje, w których musisz uzyskać kanoniczną nazwę skryptu lub innego pliku, i to jest najlepszy sposób, imo.
źródło
source
d nazw skryptów.Możesz użyć 0 $, aby określić nazwę skryptu (z pełną ścieżką) - aby uzyskać nazwę skryptu, możesz tylko przyciąć tę zmienną
źródło
jeśli wywołujesz skrypt powłoki jak
$ 0 to pełna nazwa
basename $ 0 otrzyma podstawową nazwę pliku
i musisz umieścić tę podstawową nazwę w zmiennej takiej jak
i dodaj swój dodatkowy tekst
tak jak twoje skrypty
źródło
To rozwiązuje dowiązania symboliczne (robi to realpath), obsługuje spacje (robią to podwójne cudzysłowy) i znajdzie bieżącą nazwę skryptu, nawet gdy jest pozyskiwany (. ./Myscript) lub wywoływany przez inne skrypty ($ BASH_SOURCE obsługuje to). Po tym wszystkim dobrze jest zapisać to w zmiennej środowiskowej do ponownego użycia lub łatwego kopiowania w innym miejscu (this =) ...
źródło
realpath
nie jest wbudowanym poleceniem BASH. Jest to samodzielny plik wykonywalny, który jest dostępny tylko w niektórych dystrybucjachW
bash
można uzyskać nazwę pliku skryptu za pomocą$0
. Generalnie$1
,$2
etc są do argumentów dostęp CLI. Podobnie$0
jest uzyskać dostęp do nazwy, która wyzwala skrypt (nazwa pliku skryptu).Jeśli wywołasz skrypt ze ścieżką podobną,
/path/to/script.sh
wówczas$0
również poda nazwę pliku ze ścieżką. W takim przypadku należy użyć,$(basename $0)
aby uzyskać tylko nazwę pliku skryptu.źródło
źródło
$0
nie odpowiada na pytanie (jak rozumiem). Demonstracja:Jak
./linktoscript
można wydrukowaćscript.sh
?[EDYCJA] Na @ephemient w komentarzach powyżej, chociaż łącze symboliczne może wydawać się wymyślone, można manipulować
$0
tak, aby nie reprezentował zasobu systemu plików. OP jest nieco niejednoznaczny co do tego, czego chciał.źródło
Informacje dzięki Billowi Hernandezowi. Dodałem pewne preferencje, które przyjmuję.
Twoje zdrowie
źródło
Krótkie, jasne i proste, w
my_script.sh
Wynik:
źródło
Mam powyższe pytanie z innego pytania o przepełnienie stosu. Czy skrypt Bash może określić, w którym katalogu jest przechowywany? , ale myślę, że przydaje się również w tym temacie.
źródło
Oto co wymyśliłem, zainspirowany Dimitre Radoulov odpowiedź „s (co upvoted, nawiasem mówiąc) .
niezależnie od sposobu wywołania skryptu
lub
źródło
echo „Używasz 0 $”
źródło
coś takiego?
źródło