Причина, по которой вы не можете вызвать перенаправление при расширении, "$HideErrors"
заключается в том, что подобные символы >
не обрабатываются специально после создания расширения параметра . На самом деле это очень хорошо, потому что такие символы появляются в тексте, который вы можете расширить и использовать буквально.
Это касается того, цитируете ли вы или нет $HideErrors
. Результат раскрытия параметров может быть разбит на слова и выделен, когда расширение не заключено в кавычки, но это так.
Что касается того, что с этим делать, существует множество способов добиться условного перенаправления. Для очень простой команды, может быть разумно написать целую команду дважды, один раз в каждой ветви case
или if
- else
конструкт. Однако вскоре это становится обременительным, и команда, которую вы показали, безусловно, является идеальной.
Из подходов, которые позволяют избежать повторения , есть два, которые я особенно рекомендую, потому что они довольно чистые и их легко понять. Вы хотели бы использовать только один из них, а не одновременно для одной и той же команды и перенаправления.
Сохраните команду вместо перенаправления. Вместо того, чтобы пытаться сохранить перенаправление в переменной и применять расширение параметра, сохраните команду в функции оболочки . Затем напишите a case
или if
- else
, в котором функция вызывается с перенаправлением на одной ветви и без нее на другой.
Если вы представляете свою команду как код, который вы хотите написать один раз, но выполнить при нескольких обстоятельствах, то функция является естественным решением. Это то, что я обычно делаю. Преимущество в том, что он не требует ни вложенной оболочки, ни ручного хранения и сброса состояния.
С вашим кодом:
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
Вы можете применить любой интервал, который вам нравится, или if
- else
вместо этого, если вы предпочитаете. Обратите внимание, что launch
автоматически используются вызывающая RobWebAddress
и DownloadName
переменные, даже если они являются локальными переменными, потому что Bash динамически ограничен , в отличие от большинства языков программирования с лексической областью.
Запустите команду в подоболочке и условно примените перенаправление к exec
. Это то, что прокомментировал Steeldriver , но внутри, (
)
чтобы сохранить эффект локальным . Когда встроенный запускаются без аргументов, она не заменяет текущую оболочку с новым процессом, но вместо этого применяет какое - либо из его перенаправлений к текущей оболочке.exec
(Также возможно отследить, что было стандартной ошибкой, и восстановить ее, не используя подоболочку и, следовательно, не жертвуя возможностью изменять среду текущей оболочки. Однако я оставлю подробности об этом другим ответам.)
С вашим кодом:
(
# 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"
)
После закрытия )
стандартная ошибка фактически восстанавливается до того, что было раньше, потому что она действительно перенаправляется только в подоболочку, а не в родительскую оболочку. Это также хорошо работает с существующими переменными оболочки, так как подоболочки получают их копию. Хотя я предпочитаю использовать функцию оболочки, я допускаю, что этот метод может потребовать меньше кода.
Оба метода работают независимо от того, с какого файла начинается стандартная ошибка файла или устройства, в том числе в случае перенаправлений, применяемых к функциям оболочки, которые вызывают код, содержащий условное поведение, а также в случае (упоминавшемся в вашем редактировании), где стандартная ошибка для весь сценарий уже был перенаправлен предыдущим или . То, что путь был создан путем подстановки процесса, не проблема.exec 2>&fd
exec 2> path
[[ $fCron == true ]] && exec 2>/dev/null
вместо этого