Mengapa kedua perintah 'kucing' ini menghasilkan hasil yang berbeda?

12

Mari kita asumsikan bahwa infile berisi teks tertentu, dan saya harus mengeksekusi serangkaian perintah berikut:

eksekutif 3<infile

kucing -n <&3

kucing -n <&3

Contoh pertama cat akan menampilkan konten file, tetapi yang kedua tampaknya tidak melakukan apa-apa. Mengapa mereka berbeda?

non-teroris
sumber

Jawaban:

29

Mereka terlihat seperti perintah yang sama tetapi alasan mereka berbeda adalah keadaan sistem telah berubah sebagai hasil dari perintah pertama. Secara khusus, yang pertama catmengkonsumsi seluruh file, sehingga yang kedua cattidak ada yang tersisa untuk dibaca, langsung mengenai EOF (akhir file), dan keluar.

Alasan di balik ini adalah Anda menggunakan deskripsi file yang sama persis (yang Anda buat dengan exec < infiledan ditugaskan ke deskriptor file 3) untuk kedua pemanggilan cat. Salah satu hal yang terkait dengan deskripsi file terbuka adalah offset file. Jadi, yang pertama catmembaca keseluruhan file, meninggalkan offset di bagian akhir, dan yang kedua mencoba untuk mengambil dari akhir file dan tidak menemukan apa pun untuk dibaca.

jw013
sumber
12

Hanya dengan menambahkan jawaban baik @ jw013, mungkin membantu untuk menyadari bahwa itu sama dengan

{
   cat -n
   cat -n
} < infile

< filemenjadi kependekan 0< file, yaitu menggunakan file descriptor 0 bukannya 3.

Dan sedikit membingungkan masalah ini, versi ini:

exec 3< infile
cat -n /dev/fd/3
cat -n /dev/fd/3

Berperilaku berbeda tergantung pada OS Anda menjalankannya di dan jenis dari infile(file biasa vs pipa vs perangkat ...)

Pada Solaris dan sebagian besar Unices komersial, suatu open("/dev/fd/3")kurang lebih setara dengan a dup(3)(begitu < /dev/fd/3juga dengan <&3), sementara di Linux, untuk file biasa, /dev/fd/3diimplementasikan sebagai symlink ke file asli, jadi open("/dev/fd/3")bukalah lagi dari awal ( dan mungkin dengan flag berbeda dari fd 3).

Stéphane Chazelas
sumber