La raison pour laquelle vous ne pouvez pas provoquer de redirection en développant "$HideErrors"
est que les symboles comme >
ne sont pas traités spécialement après avoir été produits par l' expansion des paramètres . C'est en fait très bon, car ces symboles apparaissent dans du texte que vous voudrez peut-être développer et utiliser littéralement.
Cela vaut que vous citiez ou non $HideErrors
. Le résultat de l'expansion des paramètres est sujet à la division et à la globalisation des mots lorsque l'expansion n'est pas citée, mais c'est tout.
Quant à ce qu'il faut faire à ce sujet, il existe de nombreuses façons d'obtenir une redirection conditionnelle. Pour une commande très simple, il peut être raisonnable d'écrire la commande entière deux fois, une fois dans chaque branche d'une construction case
ou if
- else
. Cependant, cela devient vite pénible et la commande que vous avez montrée est certainement un cas où ce ne serait pas idéal.
Parmi les approches qui vous permettent d' éviter de vous répéter , il y en a deux que je recommande particulièrement, car elles sont assez propres et faciles à bien faire. Vous souhaitez utiliser un seul d'entre eux, pas les deux à la fois pour la même commande et la même redirection.
Stockez la commande au lieu de la redirection. Au lieu d'essayer de stocker la redirection dans une variable et d'appliquer une expansion de paramètre, stockez la commande dans une fonction shell . Ensuite, écrivez un case
ou if
- else
, dans lequel la fonction est appelée avec la redirection sur une branche et sans elle sur l'autre.
Si vous conceptualisez votre commande en tant que code que vous souhaitez écrire une fois mais exécuté dans plusieurs circonstances, une fonction est la solution naturelle. C'est ce que je fais d'habitude. Il a l'avantage de ne nécessiter ni sous - shell ni stockage manuel et réinitialisation de l'état.
Avec votre code:
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
Vous pouvez appliquer l'espacement que vous souhaitez, ou if
- à la else
place si vous préférez. Notez que launch
utilise automatiquement l'appelant RobWebAddress
et les DownloadName
variables, même s'il s'agit de variables locales, car Bash a une portée dynamique , contrairement à la plupart des langages de programmation à portée lexicale.
Exécutez la commande dans un sous-shell et appliquez conditionnellement la redirection à exec
. C'est ce que Steeldriver a commenté , mais à l' intérieur (
)
pour garder l'effet local . Lorsque la fonction exec
intégrée est exécutée sans arguments, elle ne remplace pas le shell actuel par un nouveau processus, mais applique à la place l'une de ses redirections au shell actuel.
(Il est également possible de garder une trace de l'erreur standard et de la restaurer, sans utiliser de sous-shell et donc sans sacrifier la possibilité de modifier l'environnement du shell actuel. Je laisserai cependant les détails à d'autres réponses.)
Avec votre code:
(
# 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"
)
Après la fermeture )
, l'erreur standard est en effet restaurée à ce qu'elle était auparavant, car elle n'est vraiment redirigée que dans le sous-shell, et non dans le shell parent. Cela fonctionne également très bien avec les variables shell existantes, car les sous-shell en obtiennent une copie. Bien que je préfère utiliser une fonction shell, j'admets que cette méthode peut nécessiter moins de code.
Les deux méthodes fonctionnent quel que soit le fichier ou l'erreur standard de périphérique qui commence, y compris dans le cas des redirections appliquées aux fonctions shell qui appellent le code qui contient le comportement conditionnel, ainsi que le cas (mentionné dans votre modification) où l'erreur standard pour le script entier a déjà été redirigé par un précédent ou . Que le chemin ait été produit par substitution de processus ne pose aucun problème.exec 2>&fd
exec 2> path
[[ $fCron == true ]] && exec 2>/dev/null
place