Alasan Anda tidak dapat menyebabkan pengalihan terjadi dengan memperluas "$HideErrors"
adalah bahwa simbol seperti >
tidak diperlakukan secara khusus setelah diproduksi oleh ekspansi parameter . Ini sebenarnya sangat bagus, karena simbol seperti itu muncul dalam teks yang mungkin ingin Anda kembangkan dan gunakan secara harfiah.
Ini berlaku apakah Anda mengutip atau tidak $HideErrors
. Hasil ekspansi parameter tunduk pada pemisahan kata dan globbing ketika ekspansi tersebut tidak dikutip, tetapi hanya itu saja.
Adapun apa yang harus dilakukan tentang hal itu, ada banyak cara untuk mencapai pengalihan bersyarat. Untuk perintah yang sangat sederhana, mungkin masuk akal menulis seluruh perintah dua kali, sekali di setiap cabang case
atau if
- else
konstruksi. Namun, ini segera menjadi beban, dan perintah yang Anda tunjukkan tentu saja merupakan kasus yang tidak ideal.
Dari pendekatan yang memungkinkan Anda menghindari pengulangan sendiri , ada dua yang saya sarankan, karena mereka cukup bersih dan mudah diperbaiki. Anda ingin menggunakan hanya satu di antaranya, tidak sekaligus untuk perintah dan pengalihan yang sama.
Simpan perintah alih-alih pengalihan. Alih-alih mencoba menyimpan pengalihan dalam variabel dan menerapkan perluasan parameter, simpan perintah dalam fungsi shell . Kemudian tulis a case
atau if
- else
, di mana fungsi dipanggil dengan pengalihan di satu cabang dan tanpa itu di yang lain.
Jika Anda mengonseptualisasikan perintah sebagai kode yang ingin Anda tulis sekali tetapi dijalankan dalam berbagai keadaan, maka fungsi adalah solusi alami. Inilah yang biasanya saya lakukan. Ini memiliki manfaat tidak memerlukan subkulit atau penyimpanan manual dan pengaturan ulang negara.
Dengan kode Anda:
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
Anda dapat menerapkan jarak apa pun yang Anda suka, atau if
- else
sebagai gantinya jika Anda mau. Perhatikan bahwa launch
secara otomatis menggunakan pemanggil RobWebAddress
dan DownloadName
variabel, bahkan jika mereka adalah variabel lokal, karena Bash secara dinamis dicakup , tidak seperti kebanyakan bahasa pemrograman yang dibatasi secara leksikal.
Jalankan perintah dalam subkulit dan gunakan pengalihan secara kondisional exec
. Inilah yang steeldriver berkomentar tentang , tetapi di dalam (
)
untuk menjaga efek lokal . Ketika para exec
builtin dijalankan tanpa argumen, itu tidak menggantikan shell saat ini dengan proses baru, tapi bukannya berlaku setiap dari pengalihan kepada shell saat ini.
(Mungkin juga untuk melacak kesalahan standar dan mengembalikannya, tanpa menggunakan subshell dan dengan demikian tanpa mengorbankan kemampuan untuk memodifikasi lingkungan shell saat ini. Namun, saya akan menyerahkan detailnya ke jawaban lain.)
Dengan kode Anda:
(
# 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"
)
Setelah penutupan )
, kesalahan standar berlaku dikembalikan ke apa pun sebelumnya, karena itu hanya benar-benar diarahkan di subkulit, dan bukan di shell induk. Ini juga berfungsi baik dengan variabel shell yang ada, karena subshell mendapatkan salinannya. Meskipun saya lebih suka menggunakan fungsi shell, saya akui metode ini mungkin memerlukan lebih sedikit kode.
Kedua metode berfungsi terlepas dari apa standar kesalahan file atau perangkat dimulai, termasuk dalam kasus pengalihan diterapkan ke fungsi shell yang memanggil kode yang berisi perilaku kondisional, serta kasus (disebutkan dalam edit Anda) di mana kesalahan standar untuk seluruh skrip telah dialihkan oleh yang sebelumnya atau . Bahwa jalur diproduksi oleh proses substitusi tidak ada masalah.exec 2>&fd
exec 2> path
[[ $fCron == true ]] && exec 2>/dev/null
sebagai gantinya