Jak mogę określić nazwę pliku skryptu Bash w samym skrypcie?
Na przykład, jeśli mój skrypt znajduje się w pliku runme.sh
, to jak sprawiłbym, aby wyświetlał komunikat „Używasz pliku runme.sh” bez tego?
Jak mogę określić nazwę pliku skryptu Bash w samym skrypcie?
Na przykład, jeśli mój skrypt znajduje się w pliku runme.sh
, to jak sprawiłbym, aby wyświetlał komunikat „Używasz pliku runme.sh” bez tego?
Odpowiedzi:
me=`basename "$0"`
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:
me="$(basename "$(test -L "$0" && readlink "$0" || echo "$0")")"
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 symboliczne bar.sh
, wolisz użyć rozpoznanej nazwy bar.sh
zamiast foo.sh
.
$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ę 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ę.
# ------------- 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 ------------- #
show_params
, tj. Nazwę bez opcjonalnego rozszerzenia?
${0##*/}
. Testowane przy użyciu GitBash.
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"
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:
$(basename $BASH_SOURCE)
. <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.
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ż).
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_SOURCE
zmiennej ś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.
[Źródło: instrukcja Bash]
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 b
z source a
nim i uruchomisz ./b
, zwróci on b
ś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ć.
Ponieważ niektóre komentarze dotyczyły nazwy pliku bez rozszerzenia, oto przykład, jak to zrobić:
FileName=${0##*/}
FileNameWithoutExtension=${FileName%.*}
Cieszyć się!
Re: Odpowiedź Tanktalusa (zaakceptowana) powyżej, nieco czystszym sposobem jest użycie:
me=$(readlink --canonicalize --no-newline $0)
Jeśli twój skrypt pochodzi z innego skryptu bash, możesz użyć:
me=$(readlink --canonicalize --no-newline $BASH_SOURCE)
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.
source
d nazw skryptów.
jeśli wywołujesz skrypt powłoki jak
/home/mike/runme.sh
$ 0 to pełna nazwa
/home/mike/runme.sh
basename $ 0 otrzyma podstawową nazwę pliku
runme.sh
i musisz umieścić tę podstawową nazwę w zmiennej takiej jak
filename=$(basename $0)
i dodaj swój dodatkowy tekst
echo "You are running $filename"
tak jak twoje skrypty
/home/mike/runme.sh
#!/bin/bash
filename=$(basename $0)
echo "You are running $filename"
this="$(dirname "$(realpath "$BASH_SOURCE")")"
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 =) ...
realpath
nie jest wbudowanym poleceniem BASH. Jest to samodzielny plik wykonywalny, który jest dostępny tylko w niektórych dystrybucjach
W 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).
#!/bin/bash
echo "You are running $0"
...
...
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.
$0
nie odpowiada na pytanie (jak rozumiem). Demonstracja:
$ cat script.sh #! / bin / sh echo `basename $ 0` $ ./script.sh script.sh $ ln script.sh linktoscript $ ./linktoscript linktoscript
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ł.
Informacje dzięki Billowi Hernandezowi. Dodałem pewne preferencje, które przyjmuję.
#!/bin/bash
function Usage(){
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
}
Twoje zdrowie
Krótkie, jasne i proste, w my_script.sh
#!/bin/bash
running_file_name=$(basename "$0")
echo "You are running '$running_file_name' file."
Wynik:
./my_script.sh
You are running 'my_script.sh' file.
DIRECTORY=$(cd `dirname $0` && pwd)
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.
Oto co wymyśliłem, zainspirowany Dimitre Radoulov odpowiedź „s (co upvoted, nawiasem mówiąc) .
script="$BASH_SOURCE"
[ -z "$BASH_SOURCE" ] && script="$0"
echo "Called $script with $# argument(s)"
niezależnie od sposobu wywołania skryptu
. path/to/script.sh
lub
./path/to/script.sh
coś takiego?
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
fi
if [ $ans = n -o $ans = N -o $ans = no -o $ans = No -o $ans = NO ]
then
echo "'no'"
fi
return $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 Unknown
if [ -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 rental
case $val in
"trash") start_trash ;;
"help") start_help ;;
"www") firefox $homepage ;;
*) echo "Sorry, I can not get a $val for you!";;
esac
# Case stop