Aquí hay un script que cifra/descifra simétricamente un archivo con dos cifrados simétricos diferentes en secuencia.
#!/bin/bash
if [ "$#" -ne 2 ]; then
echo "Arguments: enc|dec filename"
exit
fi
E="gpg -o - --symmetric --cipher-algo"
D="gpg -o - --decrypt"
ERR="2>/dev/null"
if [ "$1" = "enc" ]; then
$E AES $2 | $E TWOFISH -
elif [ "$1" = "dec" ]; then
$D $2 ${ERR} | $D - ${ERR}
else
echo "Arguments: enc|dec filename"
exit
fi
Cuando ejecuto ./doublecrypt dec /tmp/test.encrypted
me salen los errores
usage: gpg [options] --decrypt [filename]
usage: gpg [options] --decrypt [filename]
Si cambio la línea
$D $2 ${ERR} | $D - ${ERR}
a
echo "$D $2 ${ERR} | $D - ${ERR}"
se imprime
gpg -o - --decrypt /tmp/xenc 2>/dev/null | gpg -o - --decrypt - 2>/dev/null
Si copio y pego esto en bash, se ejecuta correctamente.
Entonces, ¿por qué no funciona si elimino echo
y dejo que el script bash lo evalúe directamente, como en el formato original?
Estoy ejecutando Ubuntu Saucy y bash es mi shell.
Respuesta1
Respuesta corta: verBashFAQ #50: Estoy intentando poner un comando en una variable, ¡pero los casos complejos siempre fallan!.
Respuesta larga: tiene problemas debido al orden en que el shell analiza varios elementos de las líneas de comando; específicamente, expande las referencias variables (como ${ERR}
) aproximadamente a la mitad del proceso, después de haber tratado cosas como comillas, escapes y redirecciones. En su caso, lo que importa es la parte de redirecciones: cuando el shell se expande ${ERR}
a 2>/dev/null
, ya buscó redirecciones y no encontró ninguna, por lo que simplemente lo trata 2>/dev/null
como un argumento para el comando y luego gpg
lo rechaza por no tener sentido.
Básicamente, almacenar comandos (o elementos de comando) en variables es la forma incorrecta de hacerlo. Las variables son para datos, no para código ejecutable. En este caso, sería mucho mejor que usaras funciones:
e() {
gpg -o - --symmetric --cipher-algo "$@"
}
d() {
gpg -o - --decrypt "$@" 2>/dev/null
}
if [ "$1" = "enc" ]; then
e AES "$2" | e TWOFISH -
elif [ "$1" = "dec" ]; then
d "$2" | d -
else
echo "Arguments: enc|dec filename"
exit
fi
Tenga en cuenta que también lo puse $2
entre comillas dobles para evitar que su valor quede sujeto a la segunda mitad del proceso de análisis del shell.
Respuesta2
Intente cambiar $D $2 ${ERR} | $D - ${ERR}
a:
$( $D $2 ${ERR} | $D - ${ERR} )
Además, utilice la ruta completa a su gpg
programa, por ejemplo:
/usr/local/bin/gpg