Descrittori di file e script di shell


32

Sto facendo fatica a capire come si usano i descrittori di file negli script di shell.

Conosco le basi come

exec 5 > /tmp/foo

Quindi fd 5 è allegato a foo per la scrittura.

exec 6 < /tmp/bar

… per leggere.

exec 5>&-

... chiudi fd.

Ora cosa fa questo?

#!/bin/bash

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

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

A quanto ho capito, si &5chiude il file fd, quindi come viene ancora reindirizzato correttamente l'output dopo ogni chiamata?

Questa è una copia di pasta da: Qui

Afferma che usarlo su un semplice echo $a > filerenderebbe molto più veloce, ma non riesco a capire. Gradirei qualsiasi link a tutorial decente. I poteri di Google sembrano fallire.

Risposte:


44

Innanzitutto, nota che la sintassi per la chiusura è 5>&-o 6<&-, a seconda che il descrittore di file venga letto per la scrittura o per la lettura. Sembra che ci sia un errore di battitura o un errore di formattazione in quel post del blog.

Ecco lo script commentato.

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                  # 

Non c'è chiusura qui. Poiché tutti gli input e gli output stanno andando nella stessa posizione in questo semplice esempio, non è necessario l'uso di descrittori di file aggiuntivi. Potresti scrivere

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

L'uso di descrittori di file espliciti diventa utile quando si desidera scrivere a più file a turno. Ad esempio, si consideri uno script che trasmette i dati in un file di output dei dati e li registra in un file di registro e possibilmente anche messaggi di errore. Ciò significa che tre canali di output: uno per i dati, uno per i log e uno per gli errori. Poiché esistono solo due descrittori standard per l'output, è necessario un terzo. Puoi chiamare execper aprire i file di 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

L'osservazione sull'efficienza arriva quando si ha un reindirizzamento in un ciclo, in questo modo (supponiamo che il file sia vuoto per cominciare):

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

Ad ogni iterazione, il programma si apre /tmp/bar, cerca fino alla fine del file, aggiunge alcuni dati e chiude il file. È più efficiente aprire il file una volta per tutte:

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

Quando si verificano più reindirizzamenti in momenti diversi, execdiventa utile chiamare per eseguire reindirizzamenti anziché avvolgere un blocco in un reindirizzamento.

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

Troverai diversi altri esempi di reindirizzamento sfogliando il io-redirectiontag su questo sito .


1
La sintassi per la chiusura del descrittore di file fa effettivamente la stessa cosa.
user1338062,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.