Todo el mundo dice que eval es malo, y deberías usar $() como reemplazo. Pero me encontré con una situación en la que el sin comillas no se maneja igual dentro de $().
El fondo es que me han quemado demasiado a menudo por rutas de archivos con espacios en ellas, y me gusta citar todas esas rutas. Más paranoia sobre querer saber de dónde vienen todos mis ejecutables. Aún más paranoico, no confío en mí mismo, y me gusta poder mostrar los comandos creados que estoy a punto de ejecutar.
A continuación voy a tratar variaciones en el uso de eval vs. $(), y si el nombre del comando es citado (primo que podría contener espacios)
BIN_LS="/bin/ls"
thefile="arf"
thecmd="\"${BIN_LS}\" -ld -- \"${thefile}\""
echo -e "\n Running command '${thecmd}'"
$($thecmd)
Running command '"/bin/ls" -ld -- "arf"'
./foo.sh: line 8: "/bin/ls": No such file or directory
echo -e "\n Eval'ing command '${thecmd}'"
eval $thecmd
Eval'ing command '"/bin/ls" -ld -- "arf"'
/bin/ls: cannot access arf: No such file or directory
thecmd="${BIN_LS} -ld -- \"${thefile}\""
echo -e "\n Running command '${thecmd}'"
$($thecmd)
Running command '/bin/ls -ld -- "arf"'
/bin/ls: cannot access "arf": No such file or directory
echo -e "\n Eval'ing command '${thecmd}'"
eval $thecmd
Eval'ing command '/bin/ls -ld -- "arf"'
/bin/ls: cannot access arf: No such file or directory
$("/bin/ls" -ld -- "${thefile}")
/bin/ls: cannot access arf: No such file or directory
Así que ... esto es confuso. Una ruta de comando entre comillas es válida en todas partes, excepto dentro de un constructo $() A más corto, el ejemplo más directo:
$ c="\"/bin/ls\" arf"
$ $($c)
-bash: "/bin/ls": No such file or directory
$ eval $c
/bin/ls: cannot access arf: No such file or directory
$ $("/bin/ls" arf)
/bin/ls: cannot access arf: No such file or directory
$ "/bin/ls" arf
/bin/ls: cannot access arf: No such file or directory
¿Cómo se explica el caso simple $($c)
?
Las cadenas sin cotejar se evalúan inmediatamente. c = ("/ bin/ls"/bin/l *) hace algo bastante diferente de lo deseado. (mira con echo "'$ {c [@]}) c = ("/bin/ls ""/bin/l * ") luego z = $ (" $ {c [@]} ") falla. ¿No se puede usar una buena cantidad de argumentos con $()? – Shenme
Sin embargo, c = ("/ bin/ls" "/ bin/l *") luego z = $ ($ {c [@]}) parece funcionar bien. ¿Es este el ejecutable de $() que pretendías mostrarme? – Shenme