Por lo general, $0
en una secuencia de comandos se establece en el nombre de la secuencia de comandos, o en lo que sea que se haya invocado (incluida la ruta). Sin embargo, si uso bash
con el -c
opción, $0
se establece en el primero de los argumentos pasados después de la cadena de comando:
bash -c 'echo $0' foo bar
# foo
En efecto, parece que los parámetros posicionales se han cambiado, pero incluyen $0
. Sin embargo shift
en la cadena de comando no afecta a $0
(como siempre):
bash -c 'echo $0; shift; echo $0' foo bar
# foo
# foo
¿Por qué este comportamiento aparentemente extraño para las cadenas de comandos?
Tenga en cuenta que estoy buscando la razón, la lógica detrás de la implementación de un comportamiento tan extraño.
Se podría especular que tal cadena de comando no necesitaría el $0
parámetro como se define normalmente, por lo que por economía también se utiliza para argumentos normales. Sin embargo, en ese caso, el comportamiento de shift
es impar. Otra posibilidad es que $0
se utiliza para definir el comportamiento de los programas (a la bash
llamado como sh
o vim
llamado como vi
), pero eso no puede ser, ya que $0
aquí solo se ve en la cadena de comandos y no en los programas llamados dentro de ella. No puedo pensar en ningún otro uso para $0
, así que no puedo explicar esto.
Respuesta aceptada:
Eso le da la oportunidad de establecer/elegir $0
cuando se utiliza un script en línea. De lo contrario, $0
sería simplemente bash
.
Entonces puedes hacer, por ejemplo:
$ echo foo > foo
$ bash -c 'wc -c < "${1?}"' getlength foo
4
$ rm -f bar
$ bash -c 'wc -c < "${1?}"' getlength bar
getlength: bar: No such file or directory
$ bash -c 'wc -c < "${1?}"' getlength
getlength: 1: parameter not set
No todas las conchas solían hacer eso. El caparazón de Bourne lo hizo. El shell de Korn (y Almquist) eligió que el primer parámetro fuera a $1
en cambio. POSIX finalmente optó por el método Bourne, por lo que ksh
y ash
derivados volvieron a eso más tarde (más sobre eso en http://www.in-ulm.de/~mascheck/various/find/#shell). Eso significó que durante mucho tiempo para sh
(que, dependiendo del sistema, se basaba en el shell de Bourne, Almquist o Korn), no sabía si el primer argumento entraba en $0
o $1
, por lo que para la portabilidad, tenía que hacer cosas como:
sh -c 'echo foo in "$1"' foo foo
O:
sh -c 'shift "$2"; echo txt files are "[email protected]"' tentative-arg0 3 2 *.txt
Afortunadamente, POSIX ha especificado el nuevo comportamiento donde el primer argumento va en $0
, por lo que ahora podemos hacer de forma portátil:
sh -c 'echo txt files are "[email protected]"' meaningful-arg0-for-error *.txt