Vediamo 3 modi con cui è possibile scrivere in un file da uno script bash. Possiamo usare la redirezione dello standard output, possiamo usare il programma cat per molte linee oppure il programma tee.

Scrivere in un file usando gli operatori di redirezionamento

In bash è possibile reindirizzare l’output di un comando e scriverlo in un file. Il modo per farlo è il seguente:

program > stdout.txt
program >> append-stdout.txt

La differenza fra i due operatori:

  • > : Se il file non esiste verrà creato, se esiste ne esegue il truncate (ovvero lo azzera) e ci scrive l’output del nostro programma.
  • >>: Modalità append, se il file non esiste verrà creato, se esiste l’output verrà accodato al contenuto del file.

Bisognerà avere permessi di scrittura sul file per poter eseguire il ridirezionamento.

Possiamo utilizzare il comando “echo” built-in di bash per scrivere nel file:

echo "Hello, World!" > output.txt

E’ utile notare che la sequenza di step che esegue bash per > sono:

  1. In caso il file di output esiste, ne eseguo il truncate.
  2. Eseguo il programma e copio l’output dentro al file.

In caso il programma fallisca la sua esecuzione, il file di destinazione sarà comunque vuoto. Se non ci piace questo comportamento, possiamo anche scegliere di bloccarlo usando l’opzione noclobber:

set -o noclobber
echo "Hello, world!" > output.txt
bash: output.txt: cannot overwrite existing file

E’ possibile forzare la sovrascrittura usando >|:

echo "Hello, world!" >| output.txt

In alternativa ad echo, possiamo anche utilizzare printf:

printf "Hello, %s.\n" $USER > output.txt

Scrivere in un file usando cat

Nel caso volessimo scrivere più linee in un file da uno script bash, il modo più facile per farlo è usando heredoc (here document) e cat. Questo perchè non è possibile usare echo per stampare più linee (a meno che non siamo disposti a scrivere un echo per linea, o una unica linea con tutti i dovuti \n.)

Ecco un esempio:

cat << EOF > output.txt
Ciao $USER!
La directory corrente è: $PWD
EOF

Il formato HEREDOC viene usato in più linguaggi (come ad esempio python e perl). Funziona selezionando una keyword arbitraria, in questo caso EOF, e per segnalare la fine dell’input bisognerà inviare la keyword seguito da new line.

L’output verrà poi inserito all’interno del file output.txt

Reindirizzare e stampare l’output usando tee

Quando si costruisce una pipeline molto complicata, è spesso utile avere un’anteprima di come sono i dati che stanno transizionando fra le varie pipe. tee è un programma che ci permette proprio di fare questo.

tee legge dallo standard input e tutto ciò che riceve lo riscrive nello standard output e in uno o più file contemporaneamente.

Di default tee sovrascriverà il file di destinazione, come >. Se invece vogliamo la modalità append, bisognerà usare il parametro -a.

Eccone un esempio di utilizzo:

fponzi@home:~$ echo "this is a line" | tee output.txt
this is a line
fponzi@home~$ cat output.txt
this is a line
fponzi@home:~$ echo "this is another line" | tee -a output.txt
this is another line
fponzi@home:~$ cat output.txt 
this is a line
this is another line

Possiamo anche scrivere in più file, passando molteplici argomenti a tee, tipo tee file1 file2 file3.

Infine, un ultimo utilizzo utile di tee è quando dobbiamo scrivere il risultato di un programma in un file che richiede permessi di root. Per usare la redirezione di bash, dovremmo eseguire il comando come sudo. Usando tee, possiamo aggirare il problema.

fponzi@home:~$ sudo touch onlyroot
[sudo] password for fponzi: 
fponzi@home:~$ ls -l onlyroot 
-rw-r--r-- 1 root root 0 May 14 15:07 onlyroot
fponzi@home:~$ echo "hello, world" > onlyroot 
bash: onlyroot: Permission denied
fponzi@home:~$ echo "hello, world" | sudo tee onlyroot 
hello, world