bash - sentencias - shell script argumentos
¿Cómo paso los argumentos de script que contienen comillas/espacios? (3)
Estoy tratando de escribir un script de notify-finish
que se puede añadir a cualquier comando. Cuando termine, ejecutará el comando dado por los argumentos siguientes, luego enviará un correo electrónico al usuario cuando se complete el comando. Esto es lo que tengo:
PROG=$1
# Run command given by arguments
$@
ECODE=$?
echo -e "Subject: `hostname`: $PROG finished/r/nTo: <$USER>/r/n/r/nExited with $ECODE/r/n" | sendmail $USER
Esto funciona la mayor parte del tiempo, pero cuando los argumentos contienen espacios, la cita se elimina.
Ejemplo de trabajo:
notify-finished rsync -avz source/ user@remote:dest/
Ejemplo de falla:
notify-finished rsync -avz -e ''ssh -c blowfish'' source/ user@remote:dest/
En el segundo caso, $@
se expande a rsync -avz -e ssh -c blowfish source user@remote:dest/
, faltan las comillas simples. Tampoco funciona con comillas dobles, ni con $*
.
Después de leer otras publicaciones, intenté colocar el comando en una matriz, pero tengo el mismo problema:
CMD=(notify-finished rsync -avz -e ''ssh -c blowfish'' source/ user@remote:dest/)
${CMD[@]}
¿Cómo hago este trabajo para todos los argumentos?
Coloque comillas dobles alrededor de las sustituciones de variables para evitar que se analicen (tenga en cuenta que esto se aplica a todas las variables: $@
, $1
y $PROG
). También: no ponga un $ antes de un nombre de variable cuando se le asigne; use #
para comentarios; y, en la última línea, las comillas simples evitarán que las variables se sustituyan en absoluto.
PROG="$1"
shift
# Run program below
"$PROG" "$@"
ECODE=$? # note: this will always be a number, so it doesn''t have to be protected with double-quotes
echo -e "Subject: $(hostname): $PROG finished/r/nTo: <$USER>/r/n/r/nExited with $ECODE/r/n'' | sendmail "$USER"
Tu guión debe ser así:
# Run program below
PROG="$@"
${PROG}
ECODE=$?
echo -e "Subject: $(hostname): ${PROG} finished/r/nTo: <$USER>/r/n/r/nExited with $ECODE/r/n"
El comando final echo necesita comillas dobles en lugar de comillas simples ''
para interpretar y expandir $
variables.
Y deberías incluir el argumento de la línea de comando entre comillas dobles así como esto:
notify-finished "rsync -avz -e ''ssh -c blowfish'' source/ user@remote:dest/"
Utilice "$@"
con comillas:
prog="$1"
"$@"
ecode="$?"
echo "$prog exited with $ecode"
Esto pasará cada argumento exactamente como fue recibido. Si no incluye las citas, cada elemento se dividirá de acuerdo con $IFS
:
-
"$@"
es como"$1" "$2" "$3" ...
, pasando cada elemento como un argumento separado. -
"$*"
es como"$1 $2 $3 ..."
, pasando todos los elementos concatenados como un solo argumento -
$*
y$@
es como$1 $2 $3 ...
, dividiendo cada elemento en espacios en blanco, expandiendo todos los globos y pasando cada palabra resultante como un elemento separado ($IFS
).
Lo mismo ocurre con las matrices, como "${array[@]}"
y "${array[*]}"