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.shque é realmente um link simbólico bar.sh, você deseja usar o nome resolvido em bar.shvez de foo.sh.
-1, 1. o readlink percorre apenas um link simbólico profundo, 2. $0no 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.
Score_Under
246
# ------------- 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 ------------- #
Como obtenho apenas show_params, ou seja, o nome sem nenhuma extensão opcional?
Acumenus 08/07/2015
Não funciona caso o script seja chamado de outra pasta. O caminho está incluído no ${0##*/}. Testado usando GitBash.
AlikElzin-kilaka 30/07
1
O exemplo acima não funcionou para mim a partir de um script .bash_login, mas a solução Dimitre Radoulov do $ BASH_SOURCE funciona muito bem.
John
@ John Certamente você quer dizer .bash_profile ? Ou, alternativamente, .bashrc ? Você deve saber, porém, que existem algumas diferenças sutis na maneira como são invocadas / originadas. Estou muito cansado, mas se estiver pensando direito, esse provavelmente será o problema. Um lugar que importa é se você estiver conectado a um sistema remotamente, por exemplo, ssh versus no sistema local.
Pryftan
193
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"
Esta resposta é IMHO a melhor porque a solução utiliza código de auto-documentação. $ BASH_SOURCE é totalmente compreensível sem ler qualquer documentação enquanto por exemplo $ {0 ## * /} não é
Andreas M. Oberheim
Essa resposta é de mais valor, pois acredito que, se funcionarmos como . <filename> [arguments], $0daria o nome do shell do chamador. Bem, pelo menos no OSX, com certeza.
Mihir
68
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.
E se eu quiser, sem nenhuma extensão de arquivo opcional?
Acumenos
Para remover uma extensão, você pode tentar "$ {VARIABLE% .ext}" em que VARIABLE é o valor que você obteve de $ {0 ## * /} e ".ext" é a extensão que você deseja remover.
BrianV
19
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).
-n é inofensivo, mas não é necessário, porque a estrutura $ (...) a cortará.
zhaorufei
16
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 readlinko caminho acima, recursivamente ou não recursivamente.
A razão pela qual o one-liner funciona é explicada pelo uso da BASH_SOURCEvariá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.
Funciona se você buscar no arquivo a (suponha que ao conteúdo seja echo "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}") de uma sessão interativa - ao caminho será o mesmo. Mas se você escrever um script bcom source anele e correr ./b, ele vai voltar b's caminho.
PSKocik
12
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á.
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.
Você pode usar $ 0 para determinar o nome do seu script (com o caminho completo) - para obter o nome do script apenas você pode aparar essa variável com
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 =) ...
FYI realpathnão é um comando BASH interno. É um executável autônomo que está disponível apenas em algumas distribuições
StvnW
4
Em bashvocê pode obter o nome do arquivo de script usando $0. Geralmente $1, $2etc , 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.shentão $0também fornecerá o nome do arquivo com o caminho. Nesse caso, precisa usar $(basename $0)para obter apenas o nome do arquivo de script.
Como se consegue ./linktoscriptimprimir script.sh?
[EDIT] Por @ ephemient nos comentários acima, embora a coisa do link simbólico possa parecer artificial, é possível mexer com $0isso para que não represente um recurso do sistema de arquivos. O OP é um pouco ambíguo sobre o que ele queria.
acrescentou resposta a esta a minha resposta acima, mas eu discordo que isso é o que realmente queria (ou que você deve querer que, salvo algumas circunstâncias atenuantes que eu não posso atualmente braças)
Tanktalus
2
Eu acho que imprimir linktoscript em vez de script.sh é um recurso, não um bug. Vários comandos unix usam seu nome para alterar seu comportamento. Um exemplo é vi / ex / view.
Mouviciel 12/03/09
@Tanktalus: Há casos em que você deseja que o comportamento mude com base na localização real do arquivo - em um projeto anterior, eu tinha um script "Ramificação ativa", que ligaria o caminho para várias ferramentas da ramificação em que estive. trabalhando em; essas ferramentas poderiam descobrir em qual diretório eles foram retirados para executar nos arquivos corretos.
Andrew Aylett
2
Informação graças a Bill Hernandez. Eu adicionei algumas preferências que estou adotando.
#!/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
Respostas:
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:
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ólicobar.sh
, você deseja usar o nome resolvido embar.sh
vez defoo.sh
.fonte
$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 dissome=$(basename -- "$0")
ou muito mais eficientemente às custas da legibilidademe=${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.fonte
show_params
, ou seja, o nome sem nenhuma extensão opcional?${0##*/}
. Testado usando GitBash.Com bash> = 3, o seguinte funciona:
fonte
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:
fonte
. <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.fonte
Se você quiser sem o caminho, você usaria
${0##*/}
fonte
Para responder a Chris Conway , no Linux (pelo menos), você faria o seguinte:
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).
fonte
Descobri que essa linha sempre funciona, independentemente de o arquivo estar sendo originado ou executado como um script.
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 associadoFUNCNAME
.[Fonte: Manual do Bash]
fonte
a
(suponha quea
o conteúdo sejaecho "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}"
) de uma sessão interativa -a
o caminho será o mesmo. Mas se você escrever um scriptb
comsource a
nele e correr./b
, ele vai voltarb
'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á.
fonte
Como alguns comentários perguntaram sobre o nome do arquivo sem extensão, eis um exemplo de como fazer isso:
Aproveitar!
fonte
Re: Resposta do Tanktalus (aceita) acima, uma maneira um pouco mais limpa é usar:
Se seu script foi originado de outro script bash, você pode usar:
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.
fonte
source
nomes de scripts d.Você pode usar $ 0 para determinar o nome do seu script (com o caminho completo) - para obter o nome do script apenas você pode aparar essa variável com
fonte
se o seu invocar script de shell como
$ 0 é o nome completo
basename $ 0 obterá o nome do arquivo base
e você precisa colocar esse nome básico em uma variável como
e adicione seu texto adicional
então seus scripts como
fonte
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 =) ...
fonte
realpath
não é um comando BASH interno. É um executável autônomo que está disponível apenas em algumas distribuiçõesEm
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).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.fonte
fonte
$0
não responde à pergunta (como eu a entendo). Uma demonstração:Como se consegue
./linktoscript
imprimirscript.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.fonte
Informação graças a Bill Hernandez. Eu adicionei algumas preferências que estou adotando.
Felicidades
fonte
Curto, claro e simples, em
my_script.sh
Resultado:
fonte
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.
fonte
Aqui está o que eu vim com, inspirado por Dimitre Radoulov resposta 's (o que eu upvoted, por sinal) .
independentemente da maneira como você chama seu script
ou
fonte
eco "Você está executando $ 0"
fonte
algo assim?
fonte