tampilkan STDOUT sebelum STDERR?

9

Saya baru mengenal bash dan saya tidak bisa seumur hidup mencari tahu cara menjalankan perintah tertentu, misalkan ./fffdan cetak stdouts reguler sebelum stderr (saya bingung tentang artinya sendiri)

sebagai contoh

$ printf "I am a\ndrill\n" > fff; 
$ cat fff nofile fff nofile fff

I am a
drill
cat: nofile: No such file or directory
I am a
drill
cat: nofile: No such file or directory
I am a
drill

perlu dicetak seperti:

I am a
drill
I am a
drill
I am a
drill
cat: nofile: No such file or directory
cat: nofile: No such file or directory

Saya mengerti bahwa saya harus mengarahkan output saya terlebih dahulu ke file dan kemudian menambahkan kesalahan ke file yang sama namun ini adalah output yang saya dapatkan untuk

$ cat ./foo nofile ./foo nofile ./foo <<< $(touch fin) > see 2>> see 

I am a
drill
I am a
drill
I am a
drill
ectory
cat: nofile: No such file or directory
Meong
sumber
2
Apakah catbenar-benar mengganti "a" dengan "some"?
Dmitry Grigoryev
oh sial aku mungkin mengacaukan talinya. Saya akan segera mengeditnya @DmitryGrigoryev
MeOw

Jawaban:

18

Anda harus menahan output stderr di suatu tempat agar dapat menampilkannya di akhir.

Sebuah file muncul di benak:

fff 2> file; cat file >&2

Atau memori (di sini menggunakan spongedari moreutils):

{ fff 2>&1 >&3 3>&- | sponge >&2 3>&-; } 3>&1
  • {...} 3>&1: dalam {...}deskriptor file (fd) 3 menunjuk ke sumber yang sama dengan stdout asli (sehingga kita dapat menggunakannya untuk mengembalikan stdout untuk fff).
  • fff <redirs> | sponge <redirs>, fffdan spongemulai bersamaan (dengan <redirs>diterapkan secara independen) dengan fffstdout pergi ke pipa, dan spongestdin menjadi ujung pipa yang lain.
  • 2>&1: fd 2 of fff(stderr) menunjuk ke hal yang sama seperti pada 1: pipa pada titik ini, jadi fffkesalahannya adalah spongemelalui pipa itu.
  • >&3: sekarang stdout menunjuk ke stdout asli (mengarahkan kembali ke apa itu sebelumnya)
  • 3>&-: kita menutup fd 2 yang ffftidak perlu
  • spongemengakumulasikan inputnya dan hanya menampilkannya (pada stdout-nya yang telah dialihkan >&2ke sumber daya yang sama dengan stderr) setelah ia mendeteksi bukti pada stdin-nya (diasumsikan ketika fffmengakhiri dan telah menulis semua outputnya pada stdout-nya).

Jika spongetidak diinstal, Anda dapat menggantinya dengan perl -0777 -pe ''. Dengan -pe '', perlmembaca satu catatan sekaligus dari inputnya dan menulisnya di stdout. -0777adalah mode slurp di mana (hanya satu dalam kasus itu) catatan adalah seluruh input.

Stéphane Chazelas
sumber
Mohon uraikan jika Anda punya waktu!
George Udosen
Bisakah kita menggunakan teealih-alih sponge...?
George Vasiliou
@GeorgeUdosen lihat edit.
Stéphane Chazelas
1
@ GeorgeVasiliou, teetidak menyimpan data, ia menulisnya segera setelah membacanya.
Stéphane Chazelas
2
@ MeOw: Tidak apa-apa, tetapi, seperti yang ditunjukkan oleh baris ketiga jawaban Stéphane, Anda tidak perlu menyimpan stdout; lakukan saja cat foo nofile foo nofile foo 2> ferr.txt; cat ferr.txt. (Dan Anda mungkin tidak ingin menggunakan >>.) Juga, Stéphane membuat poin yang sangat baik yang mungkin harus Anda lakukan cat ferr.txt >&2untuk menulis informasi stderr ke stderr.
G-Man Mengatakan 'Reinstate Monica'