Geralmente, $0
em um script é definido como o nome do script ou como ele foi chamado (incluindo o caminho). No entanto, se eu usar bash
com a -c
opção, $0
será definido como o primeiro dos argumentos passados após a cadeia de comando:
bash -c 'echo $0 ' foo bar
# foo
De fato, parece que os parâmetros posicionais foram alterados, mas inclusive $0
. No entanto, shift
na cadeia de comando não afeta $0
(como normal):
bash -c 'echo $0; shift; echo $0 ' foo bar
# foo
# foo
Por que esse comportamento aparentemente estranho para cadeias de comando? Observe que estou procurando o motivo, a lógica, por trás da implementação de um comportamento tão estranho.
Pode-se especular que tal sequência de comandos não precisaria do $0
parâmetro normalmente definido, portanto, para economia, também é usado para argumentos normais. No entanto, nesse caso, o comportamento de shift
é estranho. Outra possibilidade é $0
usada para definir o comportamento dos programas (a la bash
chamado como sh
ou vim
chamado como vi
), mas isso não pode ser, pois $0
aqui é visto apenas na cadeia de comando e não pelos programas chamados dentro dela. Como não consigo pensar em outros usos $0
, não sei como explicar isso.
-
para o$0
argumento como um idioma, como emsh -c 'foo $1 $2' - a b
. Desta forma, parece muito normal (uma vez que você descobriu o que esse-
meio, que é)echo 'echo the other side of this pipe globs "$@"' | sh -s -- *
, porém, infelizmente,$0
geralmente não é um parâmetro configurável com a-s
opção tream ... No entanto, ele pode ser usado da mesma maneira quexargs
geralmente é. E outros além.--
, então isso poderia ter tido a interpretação usual de 'a partir daqui começa os argumentos', vista em alguns outros programas. Por outro lado, isso poderia confundir aqueles que não estão acostumados-c
a pensar que--
realmente têm essa interpretação.Respostas:
Isso oferece a oportunidade de definir / escolher
$0
ao usar um script embutido. Caso contrário,$0
seria apenasbash
.Então você pode fazer, por exemplo:
Nem todas as conchas costumavam fazer isso. A concha Bourne fez. O shell Korn (e Almquist) escolheu o primeiro parâmetro para ir
$1
. POSIX acabou indo para o caminho Bourne, entãoksh
eash
derivados voltou a isso mais tarde (mais sobre isso em http://www.in-ulm.de/~mascheck/various/find/#shell ). Isso significava que, por um longo período de temposh
(que, dependendo do sistema, era baseado no shell Bourne, Almquist ou Korn), você não sabia se o primeiro argumento foi inserido$0
ou$1
, portanto, para portabilidade, você precisava fazer coisas como:Ou:
Felizmente, o POSIX especificou o novo comportamento no qual o primeiro argumento entra
$0
, para que agora possamos fazer:fonte
bash -c 'echo txt files are "$@"' meaningful-arg0-for-error *.txt
no Ubuntu 14.04, festaversion 4.3.11(1)-release
, e eu tenho:txt files are *.txt
. Ootxt
arquivos no diretório atual). Veja tambémbash -c 'echo "${1?}"' foo
sh -c 'shift "$2"; echo txt files are "$@"' tentative-arg0 3 2 *.txt
é fantasticamente inventivo!SHELL -c 'shift $1; command' 2 1 arg1 arg2 ...
haha ...Esse comportamento é definido pelo POSIX :
Quanto ao motivo pelo qual você deseja esse comportamento: isso diminui a diferença entre um script e uma
-c
string. Você pode converter diretamente entre os dois sem nenhuma mudança de comportamento. Outras áreas consideram estas idênticas.Também está alinhado com o modo como os argumentos do programa funcionam em geral: isso acaba chamando uma das
exec
funções, na qual o primeiro argumento fornecido também é$0
, e igualmente comum esse argumento é o mesmo que o executável que você está executando. Às vezes, porém, você quer um valor especial lá e simplesmente não há outra maneira de obtê-lo. Dado que o argumento existe, ele precisa ser mapeado para alguma coisa, e o usuário precisa ser capaz de definir o que é isso.Essa consistência (e provável acidente histórico) leva à situação que você encontra.
fonte
argv[0]
.$0
é definido apenas comoargv[0]
passado paraexecve()
quando é parecidosh
oubash
. Para scripts,$0
é definido como o caminho fornecido como argumento 1, 2 ... para o intérprete (e para scripts executados diretamente, que vem do argumento do primeiro caminho para execve ()).