Como posso determinar o nome do arquivo de script Bash dentro do próprio script?
Como se meu script estivesse no arquivo runme.sh
, como eu faria para exibir a mensagem "Você está executando o runme.sh" sem codificar isso?
Como posso determinar o nome do arquivo de script Bash dentro do próprio script?
Como se meu script estivesse no arquivo runme.sh
, como eu faria para exibir a mensagem "Você está executando o runme.sh" sem codificar isso?
Respostas:
me=`basename "$0"`
Para ler um link simbólico 1 , que geralmente não é o que você deseja (geralmente não deseja confundir o usuário dessa maneira), tente:
me="$(basename "$(test -L "$0" && readlink "$0" || echo "$0")")"
IMO, isso produzirá resultados confusos. "Corri foo.sh, mas está dizendo que estou executando o bar.sh !? Deve ser um bug!" Além disso, um dos objetivos de ter links simbólicos com nomes diferentes é fornecer funcionalidades diferentes com base no nome que ele chama (pense em gzip e gunzip em algumas plataformas).
1 Ou seja, para resolver links simbólicos de modo que, quando o usuário executa o foo.sh
que é realmente um link simbólico bar.sh
, você deseja usar o nome resolvido em bar.sh
vez de foo.sh
.
$0
no primeiro exemplo, está sujeito à divisão de palavras, 3. $0
é passado para o nome da base, o readlink e o eco em uma posição que permite que seja tratado como uma opção de linha de comando . Sugiro em vez disso me=$(basename -- "$0")
ou muito mais eficientemente às custas da legibilidade me=${0##*/}
,. Para links simbólicos, me=$(basename -- "$(readlink -f -- "$0")")
assumindo os utilitários gnu, caso contrário, será um script muito longo que não escreverei aqui.
# ------------- SCRIPT ------------- # # ------------- CHAMADO ------ ------- #
#!/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
# Observe na próxima linha, o primeiro argumento é chamado entre aspas duplas, # e simples, pois contém duas palavras
$ / misc / shell_scripts / check_root / show_parms . sh "'olá, lá'" "'william'"
# ------------- RESULTADOS ------------- #
# argumentos chamados com ---> 'olá lá' 'william' # $ 1 ----------------------> 'olá lá' # $ 2 ---- ------------------> 'william' # path to me --------------> / misc / shell_scripts / check_root / show_parms. sh # caminho pai -------------> / misc / shell_scripts / check_root # meu nome -----------------> show_parms.sh
# ------------- FIM ------------- #
show_params
, ou seja, o nome sem nenhuma extensão opcional?
${0##*/}
. Testado usando GitBash.
Com bash> = 3, o seguinte funciona:
$ ./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
" para obter o diretório que os scripts localizaram.
$BASH_SOURCE
fornece a resposta correta ao obter o script.
No entanto, isso inclui o caminho para obter apenas o nome do arquivo dos scripts, use:
$(basename $BASH_SOURCE)
. <filename> [arguments]
, $0
daria o nome do shell do chamador. Bem, pelo menos no OSX, com certeza.
Se o nome do script tiver espaços, uma forma mais robusta é usar "$0"
ou "$(basename "$0")"
- ou no MacOS: "$(basename \"$0\")"
. Isso impede que o nome seja mutilado ou interpretado de qualquer forma. Em geral, é uma boa prática sempre citar dois nomes de variáveis no shell.
Para responder a Chris Conway , no Linux (pelo menos), você faria o seguinte:
echo $(basename $(readlink -nf $0))
O readlink imprime o valor de um link simbólico. Se não for um link simbólico, ele imprime o nome do arquivo. -n diz para não imprimir uma nova linha. -f diz para seguir o link completamente (se um link simbólico fosse um link para outro link, ele também resolveria esse).
Descobri que essa linha sempre funciona, independentemente de o arquivo estar sendo originado ou executado como um script.
echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
Se você deseja seguir os links simbólicos, use readlink
o caminho acima, recursivamente ou não recursivamente.
A razão pela qual o one-liner funciona é explicada pelo uso da BASH_SOURCE
variável de ambiente e de seu associado FUNCNAME
.
BASH_SOURCE
Uma variável de matriz cujos membros são os nomes de arquivos de origem em que os nomes das funções de shell correspondentes na variável de matriz FUNCNAME são definidos. A função shell $ {FUNCNAME [$ i]} é definida no arquivo $ {BASH_SOURCE [$ i]} e é chamada a partir de $ {BASH_SOURCE [$ i + 1]}.
FUNCNAME
Uma variável de matriz que contém os nomes de todas as funções de shell atualmente na pilha de chamadas de execução. O elemento com índice 0 é o nome de qualquer função shell em execução no momento. O elemento mais baixo (aquele com o índice mais alto) é "principal". Essa variável existe apenas quando uma função shell está em execução. As atribuições a FUNCNAME não têm efeito e retornam um status de erro. Se FUNCNAME estiver desativado, ele perderá suas propriedades especiais, mesmo que seja redefinido posteriormente.
Essa variável pode ser usada com BASH_LINENO e BASH_SOURCE. Cada elemento de FUNCNAME possui elementos correspondentes em BASH_LINENO e BASH_SOURCE para descrever a pilha de chamadas. Por exemplo, $ {FUNCNAME [$ i]} foi chamado do arquivo $ {BASH_SOURCE [$ i + 1]} na linha número $ {BASH_LINENO [$ i]}. O chamador interno exibe a pilha de chamadas atual usando essas informações.
[Fonte: Manual do Bash]
a
(suponha que a
o conteúdo seja echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
) de uma sessão interativa - a
o caminho será o mesmo. Mas se você escrever um script b
com source a
nele e correr ./b
, ele vai voltar b
's caminho.
Essas respostas estão corretas para os casos que afirmam, mas ainda existe um problema se você executar o script de outro script usando a palavra-chave 'source' (para que seja executada no mesmo shell). Nesse caso, você recebe os $ 0 do script de chamada. E, neste caso, não acho possível obter o nome do próprio script.
Este é um caso extremo e não deve ser levado muito a sério. Se você executar o script diretamente de outro script (sem 'fonte'), usar $ 0 funcionará.
Como alguns comentários perguntaram sobre o nome do arquivo sem extensão, eis um exemplo de como fazer isso:
FileName=${0##*/}
FileNameWithoutExtension=${FileName%.*}
Aproveitar!
Re: Resposta do Tanktalus (aceita) acima, uma maneira um pouco mais limpa é usar:
me=$(readlink --canonicalize --no-newline $0)
Se seu script foi originado de outro script bash, você pode usar:
me=$(readlink --canonicalize --no-newline $BASH_SOURCE)
Concordo que seria confuso remover referências de links simbólicos se seu objetivo é fornecer feedback ao usuário, mas há ocasiões em que você precisa obter o nome canônico para um script ou outro arquivo, e esse é o melhor caminho.
source
nomes de scripts d.
se o seu invocar script de shell como
/home/mike/runme.sh
$ 0 é o nome completo
/home/mike/runme.sh
basename $ 0 obterá o nome do arquivo base
runme.sh
e você precisa colocar esse nome básico em uma variável como
filename=$(basename $0)
e adicione seu texto adicional
echo "You are running $filename"
então seus scripts como
/home/mike/runme.sh
#!/bin/bash
filename=$(basename $0)
echo "You are running $filename"
this="$(dirname "$(realpath "$BASH_SOURCE")")"
Isso resolve links simbólicos (o realpath faz isso), manipula espaços (aspas duplas fazem isso) e localiza o nome do script atual mesmo quando originado (. ./Myscript) ou chamado por outros scripts ($ BASH_SOURCE lida com isso). Depois de tudo isso, é bom salvar isso em uma variável de ambiente para reutilização ou para cópia fácil em outro lugar (this =) ...
realpath
não é um comando BASH interno. É um executável autônomo que está disponível apenas em algumas distribuições
Em bash
você pode obter o nome do arquivo de script usando $0
. Geralmente $1
, $2
etc , devem acessar os argumentos da CLI. Da mesma forma $0
é acessar o nome que aciona o script (nome do arquivo de script).
#!/bin/bash
echo "You are running $0"
...
...
Se você chamar o script com o caminho como, /path/to/script.sh
então $0
também fornecerá o nome do arquivo com o caminho. Nesse caso, precisa usar $(basename $0)
para obter apenas o nome do arquivo de script.
$0
não responde à pergunta (como eu a entendo). Uma demonstração:
$ cat script.sh #! / bin / sh eco `basename $ 0` $ ./script.sh script.sh $ ln script.sh linktoscript $ ./linktoscript linktoscript
Como se consegue ./linktoscript
imprimir script.sh
?
[EDIT] Por @ ephemient nos comentários acima, embora a coisa do link simbólico possa parecer artificial, é possível mexer com $0
isso para que não represente um recurso do sistema de arquivos. O OP é um pouco ambíguo sobre o que ele queria.
Informação graças a Bill Hernandez. Eu adicionei algumas preferências que estou adotando.
#!/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
}
Felicidades
Curto, claro e simples, em my_script.sh
#!/bin/bash
running_file_name=$(basename "$0")
echo "You are running '$running_file_name' file."
Resultado:
./my_script.sh
You are running 'my_script.sh' file.
DIRECTORY=$(cd `dirname $0` && pwd)
Eu obtive o que foi dito acima em outra pergunta do Stack Overflow: um script Bash pode informar em que diretório está armazenado? , mas acho útil também para este tópico.
Aqui está o que eu vim com, inspirado por Dimitre Radoulov resposta 's (o que eu upvoted, por sinal) .
script="$BASH_SOURCE"
[ -z "$BASH_SOURCE" ] && script="$0"
echo "Called $script with $# argument(s)"
independentemente da maneira como você chama seu script
. path/to/script.sh
ou
./path/to/script.sh
algo assim?
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