Questo articolo è la seconda parte dell’ introduzione al terminale e allo scripting bash. Per leggere la prima clicca quì.

Una funzione molto ingegnosa, è la reindirizzazione dell’output: quando eseguiamo un comando, solitamente, abbiamo sempre un output.

La shell ci permette di reindirizzare ed utilizzare tale output in maniera molto facile e veloce. Mi spiego meglio.

Qualche tempo fa, volevo creare uno script in python che prendeva la lista dei file contenuti nella directory in cui l’avviavo che me li ordinava in ordine alfabetico al contrario e mi salvava tutto su un file.
Prova ad avviare questo comando da shell:

ls > listaFile.txt

In questo modo, abbiamo inserito il risultato di ls (la lista dei file) dentro al file file.txt.
Nel caso in cui avessimo voluto aggiungere il risultato di ls in coda al file (in questo caso infatti viene sovrascritto se già presente) avremmo dovuto fare:

ls >> listaFile.txt

Adesso diamo un’occhiata a quello che ha fatto, giusto per sicurezza: visto che magari la directory contiene centinaia di file,e vogliamo vederli prograssivamente, usiamo more che ci permette di scorrere schermata dopo schermata un testo:

more listaFile.txt

Se hai letto bene che volevo fare però, avrei dovuto ordinare la lista al contrario!
Diamo quindi

sort -r< listaFile.txt > listaFileInversa.txt

Il comando sort ci permette, ovviamente, di ordinare. Il parametro -r, ci permette di farlo al contrario. Dando:

sort -r < listafile.txt

Andiamo ad usare come input del sort, il contenuto del file listaFile.txt
L’output del sort poi, viene reindirizzato dentro a listaFileInversa.txt
Figo eh?
Quindi:

  • il simbolo maggiore, permette di salvare l’output di un comando dentro ad un file.
  • Il simbolo minore, permette di utilizzare un file come input di un comando

Scorrendo il terminale abbiamo scritto un sacco! Diamo clear e facciamo un pò di pulizia prima di continuare.

Un’altro simbolo utile, è il pipe: il simbolo | che si trova a sinistra dell’1, ci permette di utilizzare come input di un comando, l’output di un’altro comando.

Vediamo come è possibile, cercare dentro alla lista di file cercata poco fa, dei file che cominciano con un certo nome e ordinarli in modo corretto.

Mettiamo che nel nostro listaFileInversa.txt, abbiamo diversi file che contegano il nome prova:

grep prova listaFileInversa.txt | sort

Grep è un utile programma che ci permette di cercare un pattern in un file e, di default, lo stampa a video. Tramite | quindi, mandiamo l’output del grep come input del sort.
Grep trova tutte le stringe contenti prova, e le manda come input al sort che le ordina in modo corretto (prima erano salvate in modo inverso, ricordi?).

Terminal.hicube

Certo che Grep, come anche vim, sono ottimi programmi che vale la pena conoscere bene. Sai dove puoi trovare un manuale completo su come usare questi e gli altri comandi linux?
Praticamente sempre, in caso non ci ricordiamo qualcosa, possiamo chiedere aiuto al terminale tramite i comandi man ed help.

help grep

Non è presente la pagina di help del grep: il terminale ci consiglia di lanciare comandi alternativi. Leggiamo il manuale del grep:

man grep

Possiamo scorrere il manuale con le freccie, o a schermate con lo spazio. Per uscire ci basta premere il tasto q.

Praticamente ogni comando infatti, possiede anche delle opzioni: come abbiamo visto per il sort, possiamo definire con un meno (-) seguito da una lettera che spesso è un abbreviativo dell’opzione completa.

Vediamo un’esempio. Lanciamo man sort:

SORT(1) User Commands SORT(1)
NAME
 sort - sort lines of text files
SYNOPSIS
 sort [OPTION]... [FILE]...
 sort [OPTION]... --files0-from=F
DESCRIPTION
 Write sorted concatenation of all FILE(s) to standard output.
[...]
-r, --reverse
reverse the result of comparisons
[...]

Dando infatti –reverse, avremo lo stesso risultato di -r.

Vediamo un’altro trucchetto che ci permette di muoverci ancora più velocemente da terminale: mentre stiamo inserendo un comando, possiamo usare il tasto tab che ci permette di autocompletare il comando (o il file che stiamo specificando).
Per esempio, scrivendo “sor” e premendo tab, “sort” apparirà sullo schermo.
Premendo di nuovo tab, ci apparirà la lista dei file. Inserendo l’iniziale di un file, e premendo tab, vedremo il nome del file inserito direttamente nel terminale.

Torniamo ora a parlare di scripting e vediamo di fare qualche semplice ma utile programma.
Vediamo l’istruzione condizionale if così definita:

if condizione
then istruzione
fi

Questa ci permette di eseguire un’istruzione se una certa condizione si verifica.
Per esempio.

#Se l'utente inserisce 1, lo saluta
 read saluto
 if [ $saluto== "Ciao" ]
 then echo "Ciao, bravuomo."
 fi

fi indica la fine del blocco di istruzioni dell’ if ma possiamo usare anche elif per inserire più if in sequenza, oppure else che esegue istruzioni nel caso la condizione dell’ if non viene verificata. In tutto i casi comunque, l’if termina con un fi.
Il comando read invece legge un input da tastiera e lo inserisce nella variabile specificata dopo il comando (quindi dentro a $saluto in questo caso).

Una cosa molto utile nello scripting da shell è sfruttare l’exit status.
La variabile $? contiene il risultato di un comando: conterrà 0 (zero) se il comando è stato eseguito correttamente, altrimenti un codice corrispondente all’errore.

Nell’ espressione da controllare dell’ if (quella contenuta fra parentesi quadre), possiamo eseguire confronti fra stringhe e numeri. Per farlo però, dobbiamo usare a seconda dei casi sintassi particolari:
Se vogliamo confrontare due numeri, dobbiamo fare:

  • [ 2 -eq 3 ] per dire “2 è uguale a 3?”
  • [ 2 -ne 3 ] per dire “2 è diverso da 3?”
  • [ 2 -gt 3 ] per dire “2 è maggiore di 3?”
  • [ 2 -lt 3 ] per dire “2 è minore di 3?”
  • [ 2 -le 3 ] per dire “2 è minore-uguale 3?”
  • [ 2 -ge 3 ] per dire “2 è maggiore-uguale a 3?”

Mentre per le stringhe:

  • [ “ciao” == “ciao” ] per dire “ciao è uguale a ciao?”
  • [ “ciao” != “ciao” ] per dire “ciao è diverso da ciao?”

Esistono altri costrutti, quali for e while, che non vedremo quì ma di cui potete leggere usando il comando help.

Il bash, a differenza del batch (di windows), non supporta l’istruzione goto: questa ci permette di tornare o saltare ad una certa etichetta. Diciamo che in un certo senso semplificherebbe le cose, ma possiamo tranquillamente adattaci sfruttando le funzioni.
Le funzioni si definiscono così:

function nomeFunzione {
 comandi
 }

e richiamare poi nomeFunzione con:

nomeFunzione

Questo tipo di scrittura, ci permette di evitare di riscrivere pezzi di codice che vengono usati spesso.

Infine, ultimi comandi utili, sono per la gestione dei file:
Per creare una directory (una cartella), come già abbiamo visto usiamo il comando mkdir nomecartella.
Per cancellare un file, usiamo il comando:

rm nomeFile

Alcuni parametri utili sono -r, che permette eliminare ricorsivamente i file contenuti nella directory e tutte le sotto directory e -f e -i che permettono rispettivamente di forzare la cancellazione dei file (senza chiedere conferma) e richiede la conferma ogni volta.
Per rimuovere invece una directory, useremo il comando rmdir che sarebbe come scrivere:

rm -rf directory

su una directory.

Se dobbiamo copiare un file invece, abbiamo a disposizione il comando copy che usa questa sinassi:

cp [sorgente] [destinazione]

Mentre per spostare, usiamo mv:

mv [sorgente] [destinazione]