Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Redirezione dell'I/O

Gli strumenti per la redirezione di input ed output: conoscere i file descriptor e la sintassi per gestirli su Bash, la principale shell sui sistemi Linux.
Gli strumenti per la redirezione di input ed output: conoscere i file descriptor e la sintassi per gestirli su Bash, la principale shell sui sistemi Linux.
Link copiato negli appunti

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.


Ti consigliamo anche