La razón por la que no puede causar la redirección al expandirse "$HideErrors"
es que los símbolos como >
no son tratados especialmente después de ser producidos por la expansión de parámetros . Esto es realmente muy bueno, porque tales símbolos aparecen en el texto que tal vez desee expandir y usar literalmente.
Esto es válido tanto si cotiza como si no $HideErrors
. El resultado de la expansión de parámetros está sujeto a división de palabras y glob cuando la expansión no se cita, pero eso es todo.
En cuanto a qué hacer al respecto, hay numerosas formas de lograr la redirección condicional. Para un comando muy simple, puede ser razonable escribir todo el comando dos veces, una en cada rama de un case
o if
- else
constructo. Sin embargo, esto pronto se vuelve pesado, y el comando que mostró es ciertamente un caso en el que eso no sería ideal.
De los enfoques que le permiten evitar repetirse , hay dos que recomiendo especialmente, porque son bastante limpios y fáciles de entender. Desea usar solo uno de estos, no ambos a la vez para el mismo comando y redirección.
Almacene el comando en lugar de la redirección. En lugar de intentar almacenar la redirección en una variable y aplicar la expansión de parámetros, almacene el comando en una función de shell . Luego escriba un case
o if
- else
, en el que se llama a la función con la redirección en una rama y sin ella en la otra.
Si conceptualiza su comando como código que desea escribir una vez pero se ejecuta bajo múltiples circunstancias, entonces una función es la solución natural. Esto es lo que suelo hacer. Tiene el beneficio de no requerir ni un subshell ni almacenamiento manual y restablecimiento de estado.
Con su código:
launch() {
google-chrome --headless --disable-gpu --dump-dom \
"$RobWebAddress" > "$DownloadName"
}
case $fCron in
true) launch 2>/dev/null;;
*) launch;; # Get silly error messages when running from terminal
esac
Puede aplicar el espacio que desee o if
, else
en su lugar, si lo prefiere. Tenga en cuenta que launch
usa automáticamente la persona que llama RobWebAddress
y las DownloadName
variables, incluso si son variables locales, porque Bash tiene un alcance dinámico , a diferencia de la mayoría de los lenguajes de programación que tienen un alcance léxico.
Ejecute el comando en una subshell y condicionalmente aplique la redirección a exec
. Esto es lo que comentó Steeldriver , pero por dentro (
)
para mantener el efecto local . Cuando el exec
builtin se ejecuta sin argumentos, no reemplaza el shell actual con un nuevo proceso, sino que aplica cualquiera de sus redirecciones al shell actual.
(También es posible hacer un seguimiento de qué error estándar era y restaurarlo, sin usar un subshell y, por lo tanto, sin sacrificar la capacidad de modificar el entorno actual del shell. Sin embargo, dejaré los detalles de eso a otras respuestas).
Con su código:
(
# Suppress silly error messages unless running from terminal
case $fCron in true) exec 2>/dev/null;; esac
google-chrome --headless --disable-gpu --dump-dom \
"$RobWebAddress" > "$DownloadName"
)
Después del cierre )
, el error estándar se restaura a lo que era antes, porque solo se redirige en la subshell y no en la shell principal. Esto también funciona bien con las variables de shell existentes, ya que los subshells obtienen una copia de ellos. Aunque prefiero usar una función de shell, admito que este método puede requerir menos código.
Ambos métodos funcionan independientemente de qué error estándar de archivo o dispositivo comience, incluso en el caso de redirecciones aplicadas a funciones de shell que llaman al código que contiene el comportamiento condicional, así como el caso (mencionado en su edición) donde el error estándar para todo el script ya ha sido redirigido por un anterior o . Que el camino fue producido por la sustitución del proceso no es problemaexec 2>&fd
exec 2> path
[[ $fCron == true ]] && exec 2>/dev/null
lugar