kurang file1 file2 | kucing - mengapa ini bekerja?

21

Ketika saya menggunakan saya, less file1 file2saya mendapatkan kedua file yang ditampilkan di "less buffer viewer", tetapi less file1 file2 | catmencetak konten dari kedua file ditambahkan ke stdout. Bagaimana sedikit yang tahu jika harus menunjukkan "less buffer viewer" atau menghasilkan output ke stdout untuk perintah selanjutnya? Mekanisme apa yang digunakan untuk melakukan ini?

tfh
sumber

Jawaban:

30

lessmencetak teks ke stdout. stdout pergi

  • ke terminal (/ dev / tty?) dan membuka penampil buffer standar
  • melalui pipa ketika memipangnya ke program lain menggunakan | ( less text | cut -d: -f1)
  • ke file saat mengarahkannya dengan> ( less text > tmp)

Ada fungsi C yang disebut "isa tty " yang memeriksa apakah output akan menjadi tty (kurang 4,81, main.c, baris 112). Jika demikian, ia menggunakan penampil buffer jika tidak berperilaku seperti itu cat.

Dalam bash Anda dapat menggunakan tes (lihat man test)

  • -t deskriptor file FD FD dibuka pada terminal
  • -p FILE ada dan merupakan pipa bernama

Contoh:

[[ -t 1 ]] && \
    echo 'STDOUT is attached to TTY'

[[ -p /dev/stdout ]] && \
    echo 'STDOUT is attached to a pipe'

[[ ! -t 1 && ! -p /dev/stdout ]] && \
    echo 'STDOUT is attached to a redirection'
Michael D.
sumber
1
@ tfh Jika STDOUT tidak terpasang ke pipa atau pengalihan, benar bahwa mereka tidak mencetak bahwa STDOUT terpasang ke pipa atau pengalihan. Masukkan ketiganya dalam naskah. Panggilan bash script.sh, bash script.sh | cat, bash script.sh > file, dan melihat apa output yang Anda dapatkan.
hvd
1
stdoutbukan sesuatu yang bisa "ditulis ke file". Itu adalah sesuatu yang write() harus Anda lakukan . lesstidak harus melakukan sesuatu yang berbeda tergantung pada apakah outputnya berupa file, pipa, soket, atau perangkat blok, atau apa pun. Itu hanya masalah bahwa itu bukan tty, jadi itu hanya berperilaku seperti cat. (Saya berasumsi Anda tahu ini dan hanya memilih kata-kata yang salah untuk menjelaskannya, tetapi saya pikir saya akan menunjukkan ini untuk pembaca lain).
Peter Cordes
Jadi maksud Anda adalah kurang berperilaku seperti kucing dalam pertanyaan spesifik saya - atau lebih umum: berperilaku seperti perintah berikutnya dalam pipa. Dari apa yang saya pahami saya tidak dapat berasumsi bahwa perilaku yang sama persis diimplementasikan dalam alat yang berbeda juga.
tfh
@ tfh: Tidak, lessjangan "mencari tahu" itu catselanjutnya. Berperilaku seperti catapa pun yang terjadi selanjutnya, jika stdout bukan tty.
Peter Cordes
@MichaelD .: terima kasih, mengoreksi jawaban saya. Saya hanya menebak bahwa lessakan terus maju dan menggunakan satu TCGETS untuk mendapatkan dimensi terminal atau menemukan bahwa itu bukan tty, tetapi ternyata saya menebak salah.
Peter Cordes
6

lessmemeriksa apakah stdoutini terminal, dan berperilaku seperti catketika tidak (salinan stdin ke stdout sampai EOF).

Fitur ini memungkinkan Anda menulis skrip atau program yang selalu mengirimkan output mereka (mis. --helpOutput) melalui lesssementara masih memungkinkan pengalihan mudah ke file. Akan menyebalkan jika some_command --fullhelp > help.txtmasih menunggu spasi-stdin di halaman melalui teks, atau sesuatu. Beberapa perintah (misalnya man) memeriksa output mereka sendiri untuk memutuskan apakah akan mengirim output mereka melalui pager atau tidak. Jika Anda menjalankan man ls > ls.txt, itu tidak pernah memanggil Anda $PAGER.

lessPerilaku seperti kucing berguna jika Anda lupa mengeditnya dari satu-liner saat menambahkan lebih banyak tahapan ke saluran pipa.


lessperlu mengetahui dimensi terminal (ukuran layar, untuk mengetahui berapa banyak garis yang harus ditampilkan sekaligus). The ioctl(2)menggunakan di stdoutakan kembali ENOTTY pada non-terminal, sehingga tidak dapat menghindari penanganan kasus non-terminal pula. lesssebenarnya menggunakan isatty(3)sebelum memeriksa dimensi terminal, tetapi isattybekerja dengan mencoba ioctl hanya tty dan memeriksa kurangnya kesalahan.

Bahkan pager sederhana seperti more(1)(setidaknya versi util-linux) memiliki fitur ini, karena itu mungkin perilaku waras paling sederhana untuk diterapkan pada kasus itu.


Perhatikan bahwa ketika Anda menyalurkan sesuatu ke less (misalnya grep foo bar.txt | less), itu memang harus terbuka /dev/ttyuntuk input keyboard. (Anda dapat melihatnya melakukan ini dengan echo foo | strace less).

Peter Cordes
sumber