Diutamakan stdin dan pengalihan stdout di Bash

9

Pertanyaan saya adalah tentang pengalihan prioritas adalah bash. Misalkan Anda memiliki perintah:

cmd1 < cmd2 > cmd3

Apakah akan diterjemahkan ke:

(cmd1 < cmd2) > cmd3

Atau

cmd1 < (cmd2 > cmd3)

Deepak Mittal
sumber

Jawaban:

11

Standar POSIX menentukan bahwa pengalihan shell dari kiri ke kanan; yaitu, pesanan signifikan:

Konstruk 2>&1ini sering digunakan untuk mengarahkan kesalahan standar ke file yang sama dengan output standar. Karena pengalihan berlangsung dari awal hingga akhir, urutan pengalihan penting. Sebagai contoh:

ls > foo 2>&1

mengarahkan output standar dan kesalahan standar ke file foo. Namun:

ls 2>&1 > foo

hanya mengarahkan output standar ke file fookarena kesalahan standar diduplikasi sebagai output standar sebelum output standar diarahkan ke file foo.

bash beroperasi sesuai dengan bagian standar ini:

$ ls doesnotexist > foo 2>&1
$ cat foo
ls: cannot access doesnotexist: No such file or directory
$ ls doesnotexist 2>&1 > foo
ls: cannot access doesnotexist: No such file or directory
$ cat foo
$ 

Adapun perpipaan:

Karena penetapan jalur pipa input standar atau output standar atau keduanya terjadi sebelum redirection, maka dapat dimodifikasi oleh redirection. Sebagai contoh:

$ command1 2>&1 | command2

mengirimkan output standar dan kesalahan standar command1ke input standar command2.

Matt Eckert
sumber
Itu mengasumsikan bahwa shell Bash adalah POSIX-complient.
fpmurphy
1
Saya tidak mengerti. Karena Anda mengatakan pesanan dari kiri ke kanan, seharusnya tidak ls > foo 2>&1berarti mengarahkan redirect ke foo lalu mengarahkan redder stderr ke stdout. Jadi ini seharusnya tidak berhasil. Demikian pula perintah kedua harus bekerja. Apa yang kulewatkan di sini?
Deepak Mittal
1
@ fpmurphy bashumumnya sesuai dengan POSIX, kecuali dalam situasi yang diuraikan di sini , di mana bashperilaku default berbeda. Untuk bashlebih menyesuaikan diri, Anda dapat menggunakan --posixopsi ini.
Matt Eckert
@ dpacmittal Contoh pertama ls > foo 2>&1,, beroperasi seperti ini: pertama, output standar dialihkan ke foo, kemudian, standard error diarahkan ke output standar, yang sekarang menjadi file foo. Contoh kedua ls 2>&1 > foo, beroperasi seperti ini: kesalahan standar dialihkan ke output standar sebelum output standar dialihkan foo, sehingga kesalahan standar digema secara lokal alih-alih diarahkan ke file.
Matt Eckert
4
@ dpacmittal .. re ls 2>&1 >foo mungkin Anda bisa memikirkannya seperti ini. stderr dari 'ls' dialihkan ke stdout. Ini akan terjadi! Ini akan pergi ke mana stdout saat ini ditugaskan untuk pergi, terlepas dari arahan lebih lanjut terkait dengan stdout .. (karena ini adalah arahan utama / pertama ) .. Kemudian datang arahan lain yang mengatakan bahwa stdout akan pergi ke "foo", dan itu ... Ingat: stderr tidak berubah menjadi benar-benar menjadi stdout .. hanya pergi ke tempat stdout itu ditugaskan pada saat direktif. (mis. terminal)
Peter.O
4

Saya kira juga tidak. Sepasang tanda kurung berarti sub-shell. Tetapi dalam kasus ini, tidak ada sub-shell yang akan dimulai karena pengalihan. Bash memberi makan cmd2stdin dan memberi makan stdout cmd3.

Saya berpikir, maksud Anda kira-kira seperti apa cmd1 | cmd2 | cmd3? Karena Anda cmd2dan cmd3biasanya file biasa bukan "cmds".

MetroWind
sumber