Operatore > Redirezione dell’I/O

()

Tutti i sistemi operativi basati su Unix forniscono almeno tre diversi canali input e output – chiamati rispettivamente stdin, stdout e stderr – che permettono la comunicazione fra un programma e l’ambiente in cui esso viene eseguito.

In Bash ciascuno di questi canali viene numerato da 0 a 2, e prende il nome di file descriptor poiché fa riferimento ad un particolare file: così come avviene con un qualunque altro file memorizzato nel sistema, è possibile manipolarlo, copiarlo, leggerlo o scrivere su di esso. Bash offre anche la possibilità di aprirne di nuovi se le esigenze lo richiedono (utilizzando i numeri successivi al 2).

Quando un ambiente Bash viene avviato, tutti e tre i file descriptor di default puntano al terminale nel quale è stata inizializzata la sessione:

l’input (stdin – 0) corrisponde a ciò che viene digitato nel terminale, ed entrambi gli output

stdout (1) per i messaggi tradizionali e stderr (2) per quelli di errore – vengono inviati al terminale. Infatti, un terminale aperto in un sistema operativo basato su Unix, è in genere esso stesso un file, comunemente memorizzato in /dev/tty0; quando viene aperta una nuova sessione in parallelo ad una esistente, il nuovo terminale sarà /dev/tty1 e così via.

Perciò, inizialmente i tre file descriptor puntano tutti al file che rappresenta il terminale in cui vengono eseguiti.

L’operatore > si utilizza per effettuare il redirect dell’output. Eseguendo:

comando >file


Bash tenta prima di aprire il file con i permessi di scrittura e – nel caso questa operazione abbia successo – invia lo stream stdout al file appena aperto (sovrascrivendone il contenuto esistente). Lo stesso effetto si ottiene attraverso il comando:

comando 1>file


Il motivo è che stdout è il file descriptor numero 1. In generale è possibile scrivere comando n>file per redirezionare il file descriptor n verso file. Nel caso in cui si desideri preservare il contenuto del file e far sì che l’output stream gli venga concatenato, l’operatore da utilizzare diventa >>.

È anche possibile redirezionare sia stdout che stderr verso uno stesso file utilizzando l’operatore &> (o equivalentemente >&), cioè scrivendo:

comando &> file


Lo stesso effetto si ottiene redirezionando i due stream in sequenza, come ad esempio:

comando >file 2>&1


L’output stream viene redirezionato verso file e successivamente stderr viene redirezionato verso l’output stream, cioè file. Dato che i comandi vengono valutati sequenzialmente l’ordine in cui si specificano i redirect è significativo, perciò scrivere:

comando >file 2>&1


Non è equivalente a scrivere comando 2>&1 >file: dopo aver eseguito quest’ultimo, solo stdout sarà redirezionato verso file, poichè stderr è stato redirezionato verso la destinazione di default dell’output stream (/dev/tty0) prima che questa venisse cambiata.

Quando un comando è troppo verboso, non si è interessati al suo output o lo si vuole nascondere all’utente, è possibile redirezionare stdout o stderr (o entrambi) verso lo speciale nodo /dev/null, il cui contenuto viene sempre scartato dal sistema.

Come è facile immaginare, la redirezione di un canale di input (come quello predefinito stdin) avviene utilizzando l’operatore <: volendo dare un file in input ad un comando o ad uno script, si utilizza quindi la notazione seguente:

comando <file


Ad esempio, se vogliamo leggere il contenuto della prima riga di un file e assegnarlo alla variabile riga, è possibile semplicemente eseguire:

read -r riga < file

Infine, nel caso dei canali di input, l’operatore << seguito da un marker impone alla shell di leggere l’input da stdin fintantoché non incontra il marker; a quel punto, Bash trasmette l’intero contenuto dell’input letto fino a quel momento al canale stdin del comando che lo riceve.

Tutte le redirezioni dei canali viste finora sono state effettuate per un singolo comando; ma come si fa a stabilire una redirezione permanente dei canali I/O da un certo momento in avanti?
Tramite il comando exec:

exec 2>file
comando1
comando2


Nell’esempio appena riportato, lo stream stderr viene redirezionato verso file dal comando exec 2>file; da quel momento in avanti lo stream stderr relativo ai comandi comando1, comando2 e tutti i successivi verrà scritto nel file specificato.

Un’alternativa per effettuare il redirect soltanto temporaneo di comandi multipli verso uno stesso file si ottiene sequenzializzandoli mediante l’operatore ;:

(comando1 ; comando2) >file


Il codice precedente redireziona lo standard output di ciascun comando all’interno delle parentesi verso il file specificato.

Un altro operatore molto utile per la manipolazione degli stream I/O è quello di pipelining: |. Tramite questo simbolo, una sequenza di comandi separata da esso fa sì che ciascun comando venga eseguito allo stesso momento e che l’output di ognuno venga passato come input a quello successivo, da sinistra verso destra. Dobbiamo però fare attenzione: ogni comando viene eseguito in una subshell, perciò ogni variabile modificata da ciascuno non sarà poi letta dagli altri comandi della sequenza o nell’ambiente in cui viene eseguita l’intera pipeline, come si nota eseguendo il codice seguente:

echo “Prova” | (read var ; echo $var)


Per concludere, un comando molto utile – non fornito da Bash di default ma presente in pressoché tutti i sistemi basati su Unix – è tee: esso reindirizza lo stream input sia verso stdout sia verso un file specificato. Eseguire:

echo messaggio | tee file
stamperà messaggio a schermo e nel file specificato come argomento.

How useful was this post?

Click on a star to rate it!

Average rating / 5. Vote count:

No votes so far! Be the first to rate this post.

As you found this post useful...

Follow us on social media!

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?