Por lo general, $0
en una secuencia de comandos se establece el nombre de la secuencia de comandos, o lo que se invocó como (incluida la ruta). Sin embargo, si lo uso bash
con la -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 incluidos $0
. Sin embargo, shift
en la cadena de comando no afecta $0
(como es normal):
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 justificación, detrás de la implementación de un comportamiento tan extraño.
Se podría especular que una cadena de comandos de este tipo no necesitaría el $0
parámetro como se define generalmente, por lo que para economía también se usa para argumentos normales. Sin embargo, en ese caso el comportamiento de shift
es extraño. Otra posibilidad es que $0
se usa para definir el comportamiento de los programas (a la bash
llamada as sh
o vim
llamada as vi
), pero eso no puede ser, ya que $0
aquí solo se ve en la cadena de comandos y no por los programas llamados dentro de ella. No puedo pensar en ningún otro uso $0
, así que no puedo explicarlo.
-
para el$0
argumento como un modismo, como ensh -c 'foo $1 $2' - a b
. De esta manera se ve bastante normal (una vez que descubriste lo que eso-
significa, eso es)echo 'echo the other side of this pipe globs "$@"' | sh -s -- *
embargo, también puede , desafortunadamente,$0
generalmente no ser un parámetro configurable con la-s
opción de tream ... Sin embargo, se puede usar de muchas de las mismas manerasxargs
. Y otros además.--
, entonces eso podría haber tenido la interpretación habitual de 'desde aquí comienza los argumentos', visto en algunos otros programas. Por otra parte, eso podría confundir a aquellos que no están familiarizados con-c
pensar que--
realmente tienen esa interpretación.Respuestas:
Eso le da la oportunidad de configurar / elegir
$0
cuando usa un script en línea. De$0
lo contrario, simplemente seríabash
.Entonces puedes hacer, por ejemplo:
No todos los proyectiles solían hacer eso. El caparazón Bourne lo hizo. El shell Korn (y Almquist) eligió tener el primer parámetro en su
$1
lugar. POSIX con el tiempo se fue por la forma de Bourne, de modoksh
yash
derivados volvía al nivel más tarde (más sobre esto en http://www.in-ulm.de/~mascheck/various/find/#shell ). Eso significó que durante mucho tiemposh
(que dependiendo del sistema se basó en el shell Bourne, Almquist o Korn), no sabías si el primer argumento entró$0
o$1
, por lo que para la portabilidad, tenías que hacer cosas como:O:
Afortunadamente, POSIX ha especificado el nuevo comportamiento donde entra el primer argumento
$0
, por lo que ahora podemos hacer de forma portátil:fuente
bash -c 'echo txt files are "$@"' meaningful-arg0-for-error *.txt
en Ubuntu 14.04, fiestaversion 4.3.11(1)-release
, y tengo:txt files are *.txt
. Ootxt
archivos en el directorio actual). Ver tambiénbash -c 'echo "${1?}"' foo
sh -c 'shift "$2"; echo txt files are "$@"' tentative-arg0 3 2 *.txt
es fantásticamente inventivo!SHELL -c 'shift $1; command' 2 1 arg1 arg2 ...
jaja ...POSIX define este comportamiento :
En cuanto a por qué querrías ese comportamiento: esto suaviza la brecha entre un script y una
-c
cadena. Puede convertir directamente entre los dos sin ningún cambio de comportamiento. Otras áreas confían en que estas sean idénticas.También está en línea con la forma en que funcionan los argumentos del programa en general: en última instancia, esto se reduce a llamar a una de las
exec
funciones, en la que también está el primer argumento proporcionado$0
, e igualmente comúnmente ese argumento es el mismo que el ejecutable que está ejecutando. A veces, sin embargo, desea un valor especial allí, y simplemente no habría otra forma de obtenerlo. Dado que el argumento existe, tiene que asignarse a algo, y el usuario debe poder establecer qué es eso.Esta coherencia (y probable accidente histórico) conduce a la situación que encuentra.
fuente
argv[0]
.$0
solo se establece en elargv[0]
pasado aexecve()
cuando es comosh
obash
. Para los scripts,$0
se establece en la ruta dada como argumento 1, 2 ... al intérprete (y para los scripts ejecutados directamente, eso proviene del primer argumento de ruta a execve ()).