¿Hay alguna manera de redirigir stdout y stderr a través de variables como agregar opciones de comando en el script?
Por ejemplo tengo un script:
#!/bin/bash -x
TEST=">/dev/null 2>&1"
OPT='-p -v'
mkdir $OPT 123/123/123 $TEST
Puedo ver que OPT se reemplaza -p
sin problemas y bash lo interpreta como una opción. Pero la redirección se interpreta como el nombre de los directorios.
$ ./test.sh
+ TEST='>/dev/null 2>&1'
+ OPT='-p -v'
+ mkdir -p -v 123/123/123 '>/dev/null' '2>&1'
mkdir: created directory `123/123'
mkdir: created directory `123/123/123'
mkdir: created directory `>/dev'
mkdir: created directory `>/dev/null'
mkdir: created directory `2>&1'
¿Hay alguna manera de decir bash, que $ VAR es redirección, no nombres de directorios?
PD. Puede ser que estoy en el camino equivocado, pero quiero hacer una salida detallada o no detallada de mi script. Pero necesito algo de salida incluso en modo no detallado, por lo tanto, no puedo simplemente redirigir stdout y stderr completos, solo desde algunos comandos dentro de mi script.
El "cómo" se ha explicado bien en otras respuestas; Quiero abordar el "por qué" el código del OP no funciona.
La nota clave es que las redirecciones de salida se marcan antes de la expansión variable. Las redirecciones se realizan realmente después de la expansión de la variable (de ahí que se pueda redirigir la salida a un nombre de archivo que se almacena en una variable), pero el shell identifica las redirecciones para el procesamiento posterior antes de que las variables se expandan.
En otras palabras, una vez que se expanden las variables, es "demasiado tarde" para un carácter de redireccionamiento (
<
o>
, etc.), porque el shell ya ha identificado qué partes de la cadena de comandos manejará como redireccionamientos.Para leer más, vea los pasos 1 y 3 enumerados a continuación:
fuente
No se interpreta como un "nombre de directorio",
>
se cita, por lo que se trata literalmente (más específicamente, está enviando la cadena>dev/null 2>&1
. Su única forma de evitar esto es usandoeval
o generar un nuevo shell.En cuanto a su problema "detallado" aludido en su pregunta, simplemente haga esto en su lugar:
fuente
Tiene muchos espacios en sus variables, que no se evaluarán correctamente. Querrá usar
eval
para configurar eso.Esto permitirá que $ OPT se divida en dos argumentos (
-p
y-v
) en lugar de uno (-p -v
) y lo mismo con $ TEST. También se cambió para usar,/dev/null
ya que es muy poco probable que tenga undev
directorio en el directorio actual.fuente
La respuesta de enzotib usa una buena magia de descriptores de archivos, pero una solución más simple sería usar
eval
la línea (que sin embargo agrega una sobrecarga del proceso):fuente