Soy bastante nuevo en las secuencias de comandos Bash. Tengo un "script de prueba", que utilicé como base para un script más avanzado / útil:
#!/bin/bash
files=$1
for a in $files
do
echo "$a"
done
Cuando llamo a esto sin comillas, solo recoge un archivo en un directorio:
testscript *.txt
Pero cuando lo llamo con comillas, funciona correctamente y selecciona todos los archivos de texto:
testscript '*.txt'
¿Que esta pasando aqui?
bash
shell-script
gornvix
fuente
fuente
for a in "$@"; do
(ofor a; do
) en su secuencia de comandos, dejando de este modo la capa exterior, no dejar de lado las comillas.Respuestas:
Cuando llamas a un programa
entonces su shell hace la expansión y calcula todos los valores. Por lo tanto, podría llamar efectivamente a su programa como
Ahora su programa solo mira
$1
y solo funcionafile1.txt
.Al citar en la línea de comando, está pasando la cadena literal
*.txt
al script, y eso es lo que se almacena$1
. Sufor
ciclo luego lo expande.Normalmente lo usarías
"$@"
y no$1
en scripts como este.Este es un "problema" para las personas que provienen de las secuencias de comandos CMD, donde el shell de comandos no hace glob (como se sabe) y siempre pasa la cadena literal.
fuente
"$@"
(en lugar de$@
o$1
$2
$3
) hará que se cite cada nombre de archivo,"file1.txt"
"file2.txt"
etc. Parafile1.txt
esto no tiene sentido, pero si lo tienemy file.txt
, la cita es crítica para evitar el shell análisis para convertirlo en dos nombres de archivo, uno con nombremy
y otro con nombrefile.txt
. Siempre cite la entrada del usuario y la expansión global para que no se sienta muy infeliz algún día.Sin comillas, el shell se expande
*.txt
antes de invocar el script, por$1
lo que solo se expande el primer archivo. Todos lostxt
archivos son argumentos de su secuencia de comandos en ese punto (suponiendo que no haya demasiados).Con comillas, esa cadena se pasa sin expandirse al script, lo que luego le permite
for
hacer la expansión, como espera.fuente