Причина, через яку ви не можете спричинити перенаправлення шляхом розширення, "$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
замість цього