Deskriptor file & skrip shell

32

Saya mengalami kesulitan memahami bagaimana seseorang menggunakan deskriptor file dalam skrip shell.

Saya tahu dasar-dasar seperti

exec 5 > /tmp/foo

Jadi fd 5 dilampirkan ke foo untuk menulis.

exec 6 < /tmp/bar

… untuk dibaca.

exec 5>&-

… Tutup fd.

Sekarang apa fungsinya?

#!/bin/bash

exec 5 > /tmp/foo 
exec 6 < /tmp/bar 

cat <&6 | while read a
do
     echo $a >&5
done

Seperti yang saya pahami &5menutup fd, jadi bagaimana output masih diarahkan kembali dengan sukses setelah setiap panggilan?

Ini adalah salinan dari: Di sini

Ini mengklaim menggunakan ini lebih sederhana echo $a > fileakan membuatnya lebih cepat, namun saya gagal untuk mengerti. Saya akan menghargai tautan apa pun ke tutorial yang layak. Saya kekuatan Google tampaknya mengecewakan saya.

Ricko M
sumber

Jawaban:

44

Pertama, perhatikan bahwa sintaks untuk penutupan adalah 5>&-atau 6<&-, tergantung pada apakah deskriptor file sedang dibaca untuk ditulis atau untuk dibaca. Tampaknya ada kesalahan ketik atau kesalahan format dalam posting blog itu.

Inilah skrip yang dikomentari.

exec 5>/tmp/foo       # open /tmp/foo for writing, on fd 5
exec 6</tmp/bar       # open /tmp/bar for reading, on fd 6
cat <&6 |             # call cat, with its standard input connected to
                      # what is currently fd 6, i.e., /tmp/bar
while read a; do      # 
  echo $a >&5         # write to fd 5, i.e., /tmp/foo
done                  # 

Tidak ada penutupan di sini. Karena semua input dan output akan pergi ke tempat yang sama dalam contoh sederhana ini, penggunaan deskriptor file tambahan tidak diperlukan. Anda bisa menulis

cat </tmp/bar |
while read a; do
  echo $a
done >/tmp/foo

Menggunakan deskriptor file eksplisit menjadi berguna ketika Anda ingin menulis ke beberapa file secara bergantian. Misalnya, pertimbangkan skrip yang menampilkan data ke file keluaran data dan mencatat data ke file log dan mungkin pesan kesalahan juga. Itu berarti tiga saluran keluaran: satu untuk data, satu untuk log dan satu untuk kesalahan. Karena hanya ada dua penjelas standar untuk keluaran, yang ketiga diperlukan. Anda dapat menelepon execuntuk membuka file output:

exec >data-file
exec 3>log-file
echo "first line of data"
echo "this is a log line" >&3

if something_bad_happens; then echo error message >&2; fi
exec >&-  # close the data output file
echo "output file closed" >&3

Komentar tentang efisiensi muncul ketika Anda memiliki pengalihan dalam satu lingkaran, seperti ini (anggap file kosong untuk memulai):

while …; do echo $a >>/tmp/bar; done

Pada setiap iterasi, program terbuka /tmp/bar, mencari ke akhir file, menambahkan beberapa data dan menutup file. Lebih efisien untuk membuka file sekali dan untuk semua:

while …; do echo $a; done >/tmp/bar

Ketika ada beberapa pengalihan terjadi pada waktu yang berbeda, panggilan execuntuk melakukan pengalihan daripada membungkus blok dalam pengalihan menjadi berguna.

exec >/tmp/bar
while …; do echo $a; done

Anda akan menemukan beberapa contoh pengalihan dengan menjelajahi io-redirectiontag di situs ini .

Gilles 'SANGAT berhenti menjadi jahat'
sumber
1
Entah sintaks untuk menutup file descriptor sebenarnya melakukan hal yang sama.
user1338062