Nel mondo dell'interfaccia a riga di comando, i programmi interagiscono spesso con tre flussi di dati standard:
stdin): dove un programma riceve il proprio input (di solito dalla tastiera).stdout): dove un programma invia il proprio output normale (di solito allo schermo del terminale).stderr): dove un programma invia i messaggi di errore (di solito allo schermo del terminale).Ricorda che li abbiamo presentati nel capitolo Pipeline e liste di comandi.
Le pipeline si possono considerare una forma di redirezione: l'output standard di un programma viene inviato direttamente all'input standard di un altro. Abbiamo già visto le pipeline. Questo concetto riguarda invece la redirezione da e verso i file.
La redirezione della shell è un meccanismo potente che ti permette di cambiare la destinazione di questi flussi. Invece di far leggere a un programma dalla tastiera o di fargli scrivere sullo schermo, puoi redirigere l'input da un file o inviare l'output a un file. Questo offre notevole flessibilità e controllo su come i programmi interagiscono con i dati.
Ecco i più comuni operatori di redirezione e cosa fanno:
> (redirezione dell'output)Scopo: redirigere l'output standard (stdout) di un comando verso un file.
Comportamento:
Esempio:
# Sends the output of 'ls -l' to 'file_listing.txt'
ls -l > file_listing.txt
La redirezione avviene prima che il comando venga eseguito. Questo significa che non puoi redirigere verso lo stesso file da cui devi leggere.
date > date.txt # populate the file with the current date
cat date.txt > date.txt # 'date.txt' is now empty!
Nel secondo comando dell'esempio qui sopra,
>> (redirezione dell'output in aggiunta)Scopo: aggiungere l'output standard (stdout) di un comando in fondo a un file.
Comportamento:
Esempio:
# Adds "Another line" to the end of the file
echo "Another line" >> file_listing.txt
< (redirezione dell'input)Scopo: redirigere l'input standard (stdin) di un comando da un file.
Comportamento: il comando legge il proprio input dal file indicato invece che dalla tastiera.
Esempio:
# 'tr' reads from 'lowercase.txt' and
# output is redirected to 'uppercase.txt'
tr 'a-z' 'A-Z' < lowercase.txt > uppercase.txt
2> (redirezione degli errori):stderr) di un comando verso un file.# Error message from 'rm' is sent to 'error_log.txt'
rm non_existent_file 2> error_log.txt
Puoi aggiungere l'errore standard a un file con 2>>.
Esistono anche redirezioni che possono unire sia stdin sia stderr.
Consulta il manuale per i dettagli.
/dev/null/dev/null è un file speciale che
A volte viene chiamato «the bitbucket». È utile per sopprimere l'output o gli errori.
some_command > /dev/null # Discards stdout
some_command 2> /dev/null # Discards stderr
# Using /dev/null as input will prevent the command
# from reading data from the keyboard
some_command < /dev/null
Puoi indicare più redirezioni contemporaneamente.
some_command < input.txt > output.txt 2> error.txt
Una redirezione può essere copiata.
# send stderr to the same destination as stdout
some_command > output.txt 2>&1
Quando vedi 2>&1, leggilo come «redirigi stderr verso qualunque cosa stdout stia puntando in questo momento».
Bash elabora le istruzioni di redirezione rigorosamente da sinistra a destra, il che significa che puoi fare così:
# redirect stdout to 'output1.txt'
# redirect stderr to the same place
# then change stdout to 'output2.txt'
some_command > output1.txt 2>&1 > output2.txt
Nel contesto della programmazione della shell e dei sistemi operativi come Linux/Unix, un descrittore di file (FD) è un numero intero non negativo che funge da identificatore o riferimento per un file aperto o una risorsa di I/O (Input/Output). Immaginalo come un'etichetta o un numero di riferimento che il sistema operativo usa per tenere traccia dei file aperti e dei flussi di dati.
I numeri che vedi a sinistra delle redirezioni sono descrittori di file.
Ai flussi di I/O standard vengono assegnati i primi 3 descrittori di file:
Nuovi descrittori di file possono essere impostati o creati con il comando exec e gli operatori di redirezione.
# create FD 3 as a copy of stdout
exec 3>&1
# send stdout to a log file
exec > log.txt
# then redirect both stdout and file descriptor 3
echo "some debug message" >&3 # displayed in the terminal
some_command 2>&1 # stdout and stderr send to 'log.txt'
Questa tecnica sembra piuttosto contorta, ma può essere molto utile quando lo script viene eseguito da un altro software e l'output standard viene catturato automaticamente dal programma.
Il comando bats, usato per eseguire i test unitari di questo track, funziona così: bats cattura lo stdout e lo stderr di un test, ma i messaggi di debug inviati al FD 3 vengono mostrati sul terminale.
Perché la redirezione è utile?
Le redirezioni della shell ti danno un controllo molto preciso su come i programmi interagiscono con i dati, permettendoti di costruire flussi di lavoro complessi e di gestire le informazioni in modo efficace.