Bagaimana cara kerja `cat <> file`?

42

cat < filemencetak isi file ke stdout.

cat > filemembaca stdin hingga Ctrl+ Dterdeteksi dan teks input ditulis ke file .

cat <> file, setidaknya dalam versi Bash saya, mencetak konten file dengan senang hati (tanpa kesalahan), tetapi tidak memodifikasi file juga tidak memperbarui cap waktu modifikasi.

Bagaimana standar Bash membenarkan yang tampaknya diabaikan >dalam pernyataan ketiga - dan, yang lebih penting, apakah itu melakukan sesuatu?

Qix
sumber

Jawaban:

47

Bash menggunakan <>untuk membuat deskriptor file baca-tulis :

Operator pengalihan

[n]<>word

menyebabkan file yang namanya perluasan kata akan dibuka untuk membaca dan menulis pada deskriptor file n, atau pada deskriptor file 0 jika n tidak ditentukan. Jika file tidak ada, itu dibuat.

cat <> filemembuka fileread-write dan mengikatnya ke deskriptor 0 (input standar). Ini pada dasarnya setara dengan < fileuntuk setiap program yang ditulis secara masuk akal, karena tidak ada yang cenderung mencoba menulis ke input standar biasanya, tetapi jika ada yang melakukannya akan mampu.

Anda dapat menulis program C sederhana untuk menguji bahwa secara langsung - write(0, "hello", 6)akan menulis helloke dalam filemelalui input standar.

<>juga harus bekerja di shell yang sesuai dengan POSIX lainnya dengan efek yang sama.

Michael Homer
sumber
1
Menulis ... ke stdin? ... Apakah ada kasus penggunaan yang valid untuk ini?
Qix
3
Begitu saja, saya tidak bisa memikirkan yang bagus. Memberikan deskriptor eksplisit ( 4<>file) berguna, dan saya kira 0 sama bagusnya dengan default ketika Anda meninggalkannya. Membaca dari stdout tidak lebih baik.
Michael Homer
5
<>juga berguna pada beberapa sistem (seperti Linux) untuk membuka pipa bernama tanpa memblokir sampai proses lain membukanya untuk penulisan.
Stéphane Chazelas
1
@Qix: Tulis dengan baik (0, "Kata Sandi:", 10) adalah cara yang baik untuk meminta kata sandi jika Anda berniat meminta sesuatu seperti tty. Saya terbiasa melihatnya hanya pada stderr tetapi tidak ada alasan khususnya teknik yang sama tidak bekerja pada stdin.
Joshua
3
@Qix - from the POSIX Rationale - <>Operator dapat berguna dalam menulis aplikasi yang bekerja dengan beberapa terminal, dan sesekali ingin memulai sebuah shell. Shell itu pada gilirannya tidak akan dapat menjalankan aplikasi yang berjalan dari terminal pengendali biasa kecuali jika ia dapat menggunakan <>... seperti ... pager more, yang membaca dari kesalahan standar untuk mendapatkan perintahnya, sehingga input standar dan output standar keduanya tersedia untuk penggunaan biasa. cat food | more - >/dev/tty03 2<>/dev/tty03
mikeserv
38

<> filemembuka file (pada deskriptor file 0 (stdin) secara default, seperti <) dalam mode baca + tulis tanpa pemotongan dan membuat file jika tidak ada sebelumnya .

Itu sesuai dengan O_RDWR|O_CREATbendera yang diteruskan ke open()panggilan sistem. Sebaliknya <ada O_RDONLYdan >ada O_WRONLY|O_CREAT|O_TRUNCdan >> O_WRONLY|O_CREAT|O_APPEND.

Memiliki stdin yang dapat ditulisi tidak sering berguna karena aplikasi biasanya tidak menulis ke stdin mereka. Aplikasi biasanya tidak berharap untuk membaca dan menulis pada deskriptor file yang mereka terima saat startup; mereka biasanya membaca dari stdin (atau file deskriptor yang mereka buka sendiri) dan menulis ke stdout atau stderr (atau file deskriptor yang mereka buka sendiri).

<> dapat memiliki kegunaannya:

  • Anda dapat memilih cat <> filelebih dari itu cat < filejika Anda tidak ingin perintah gagal jika filetidak ada, tetapi sebagai filegantinya dibuat.
  • Aspek non-pemotongan <>membuatnya berguna untuk menimpa file di tempat. Namun dalam hal itu, Anda biasanya tidak menggunakannya pada deskriptor file 0:

    printf xxx 1<> file

    menggantikan 3 byte pertama filedengan xxx.

  • Pada beberapa sistem seperti Linux, <>pada pipa bernama (FIFO) membuka pipa bernama tanpa menghalangi (tanpa menunggu beberapa proses lain untuk membuka ujung lainnya), dan memastikan struktur pipa dibiarkan hidup. Misalnya di:

    mkfifo pipe; sed 's/foo/bar/g' <> pipe

    sedmenangani data yang masuk dari sejumlah proses lain yang menulis dan tidak pernah melihatnya eof.

Stéphane Chazelas
sumber
1
Perhatikan bahwa pada AT&T ksh93, <>default ke 1<>(stdout) bukan 0<>(stdin). Ini adalah bug kepatuhan POSIX yang saya laporkan dan akan diperbaiki pada rilis berikutnya. github.com/att/ast/issues/75 Tapi sampai versi ksh93 saat ini tidak digunakan, Anda harus memasukkan nomor deskriptor file untuk digunakan dengan mudah <>.
Martijn Dekker
@ MartijnDekker, aku tahu, akulah yang pertama kali memberitahumu tentang hal itu ;-). Perhatikan bahwa ini hanya untuk ksh93t + (di mana perilaku berubah) dan di atasnya.
Stéphane Chazelas
Apa (atau) sistem yang tidak seperti Linux di mana mkfifo fifo; exec 3<>fifoakan diblokir?
Paman Billy