Generalità sui comandi

L'interazione in un terminale avviene tramite l'inserimento di appositi comandi. Ogni comando è in realtà il nome di un programma, che viene ricercato in alcune cartelle pre-determinate. Solitamente queste sono /bin, /usr/bin, e talvolta /usr/local/bin. In quest'ultima cartella è usuale installare nuovi comandi creati dall'utente, oppure installati come applicazioni di terze parti.

Il comando ls

Uno dei primi comandi con cui si fa conoscenza è ls, che sta per "list"; è già stato usato per ottenere la lista dei file nella propria home. Permette di ottenere una lista dei file in una directory qualunque.

Si utilizzi il comando ls per ottenere una lista dei file nella directory corrente. Ad esempio:
$ ls
Se la cartella è vuota, ci si aspetta che il comando non ritorni nessun output. Tuttavia, nella home ci sono dei file, solamente che sono nascosti, perché il loro nome comincia con un punto. Per visualizzare la lista completa dei file si può dare il comando ls -a.

Si noti che, quando viene chiesto di vedere anche i file nascosti, vengono sempre mostrati due file particolari:

Ogni comando può accettare degli argomenti, ovvero una lista di stringhe (i.e., sequenze di caratteri) successive al nome del comando, che si possono utilizzare per specificare l'azione da effettuare. Queste vengono usualmente distinte in opzioni, o flag, che tipicamente iniziano con il simbolo -, e genericamente argomenti (tutti gli altri).

Tipicamente i flag si distinguono in quelli brevi, identificati da una linea ed una sola lettera, e quelli lunghi, che iniziano con due linee seguita poi da parola chiave più lunga. A volte esiste solo una versione (lunga o corta), mentre altre volte sono accettate entrambe le possibilità. Ad esempio, è possibile chiedere a ls di invertire l'ordine in cui vengono listati gli argomenti utilizando il flag -r, oppure --reverse.

È possibile utilizzare la flag -l per chiedere a ls una lista più dettagliata, oppure specificare come argomento il nome di una cartella diversa da quella corrente di cui listare il contenuto. Non esiste una versione lunga di questa opzione.

Si utilizzi la flag -l per chiedere ad ls di fornire una lista dettagliata del contenuto della cartella ~/.ssh/, dove nell'esercizio precedente dovrebbero essere state salvate le chiavi crittografiche. Il comando dovrà restituire un output simile al seguente:
ls -l ~/.ssh
-rw------- 1 leonardo leonardo   396 lug  3 08:23 authorized_keys
-rw-rw-r-- 1 leonardo leonardo   888 lug 21 16:23 config
-rw------- 1 leonardo leonardo  1679 lug  3 08:23 id_rsa
-rw-r--r-- 1 leonardo leonardo   396 lug  3 08:23 id_rsa.pub
-rw-r--r-- 1 leonardo leonardo 91416 lug 21 16:06 known_hosts
Hint: si torni all'esercizio 1 per vedere come digitare il simbolo ~.
Dall'output di ls -l si ottengono molte informazioni, organizzate per colonne. Possiamo analizzare ad esempio il file id_rsa.pub, la chiave pubblica utilizzata per l'autenticazione.

Il comando man

Come fare a sapere quali opzioni accetta un comando? Ad esempio, è possibile chiedere al comando ls di listare i file in ordine alfabetico inverso? In generale ci sono due strategie per rispondere a questa domanda:

Per aprire il manuale di un comando si utilizza il comando man.

Si consulti il manuale del comando ls usando il comando man ls; si determini l'opzioni necessaria per invertire l'ordine degli elementi, e la si usi per ottenere una lista dei file nella directory corrente in ordine alfabetico inverso. Per uscire dal manuale, si utilizza il tasto q.
Curiosità: È disponibile anche il manuale del manuale, tramite il comando man man.

Redirigere l'output

Un comando lanciato da terminale può stampare dell'output, e leggere dell'input. Per la seconda operazione, utilizza un canale detto standard input, abbrevito in stdin. Per stampare, invece, esistono due possibilità: lo standard output (stdout), e lo standard error (stderr). A prima vista, le stampe effettuate su questi due canali appaiono identiche, ma è possibile trattarle in modo diverso.

Molto spesso può essere utile salvare l'output di un comando su un file, invece di visualizzarlo sul terminale. Per ottenere questo effetto, è sufficiente utilizzare il simbolo >. Questo è uno speciale comando che permette di redirigere lo standard output su un file, ad esempio con la sintassi:

$ miocomando > miofile.txt

Per impratichirsi con la redirezione dell'output, è molto utile il comando echo, che semplicemente stampa gli argomenti che gli vengono passati. Ad esempio:

$ echo ciao
ciao

Il terminale interpreta gli spazi come separazione degli argomenti passati ad un comando, per cui l'istruzione echo ciao a tutti viene interpretata come un comando con tre argomenti, rispettivamente ciao, a, e tutti. Normalmente, echo stampa tutti gli argomenti che riceve separati da spazi, quindi l'effetti finale del comando

$ echo ciao a tutti
è apparentemente quello atteso. Tuttavia, cosa succede aggiungendo ulteriori spazi fra le parole? Per fare in modo che il comando echo tratti l'argomento come unico, dobbiamo usare le virgolette:
$ echo "ciao a tutti"
oppure
$ echo 'ciao a tutti'
L'uso degli apici singoli o doppi non è equivalente, ma la differenza verrà discussa quando si parlerà di variabili.

Provare a combinare il comando echo con la redirezione dell'output per creare un file prova.txt che contenga il testo "Questo è un file di prova". Verificare il contenuto del file con il comando cat prova.txt.

Lo standard error viene utilizzato solitamente per i messaggi d'errore. Rediregere l'output con > non ha effetto su queste stampe.

Provare a dare il comando ls file-che-non-esiste, dove file-che-non-esiste è un qualsiasi nome di file che non esiste nella directory corrente. Il comando stamperà un messaggio d'errore. Provare a redirigere l'output su un file, ad esempio output.txt, ad esempio con il comando
$ ls file-che-non-esiste > output.txt
Cosa succede? Cosa contiene il file output.txt? Controllare con il comando cat.

I canali stdin,stdout, e stderr, sono identificati dal sistema operativo con dei numeri interi, detti file descriptor. In particolare, questi sono rispettivamente 0, 1, e 2.

È possibile usare questi interi per redirigere un canale diverso dallo standard output, ad esempio:
$ ls file-che-non-esiste 2> output.txt > output1.txt
redirige lo stderr sul file output.txt, e lo standard output su output1.txt. Confrontare il comportamento con il comando precedente.

È possibile usare una sintassi simile per redirigere un canale nell'altro. Ad esempio, tramite il comando:

$ ls file-che-non-esiste 2>&1
si può mandare lo stderr nello stdout. Il simbolo &1 sta ad indicare l'indirizzo dello stream identificato dall'intero 1. La sintassi è molto simile a quella utilizzata in C per ottenere l'indirizzo in memoria di una variabile.

Sostituendo il simbolo > con >>, è possibile concatenare del testo ad un file già presente; il simbolo >, al contrario, sovrascrive sempre il contenuto del file. Anche questo simbolo si può far precedere dall'intero che rappresenta lo stream, ad esempio 2>> per lo stderr.

In maniera analoga, è possibile utilizzare un file come input di un comando, tramite il simbolo <. Ad esempio, supponiamo di avere il file miofile.txt salvato nella directory corrente. Allora il comando

$ comando < miofile.txt
leggerà il contenuto del file come input, invece che chiederlo all'utente.

Comporre comandi diversi

Una potente caratteristica del terminale in Linux è che permette di comporre i comandi come fossero funzioni, fornendo l'output di uno come input dell'altro. La notazione matematica $g\circ f(x) = g(f(x))$ in un terminale si scrive come f | g.

Per fare un esempio pratico, si consideri un nuovo comando, di nome bc. Questo è una specie di calcolatrice, che a meno di impostazioni diverse lavora con gli interi.

Provare a lanciare il comando bc, ed inserire qualche operazione aritmetica (ad esempio: 2 + 3, o 8 / 5); verificare il funzionamento del programma, e poi digitare la combinazione di tasti CTRL + D per uscire (oppure scrivere quit e premere invio).

È possibile utilizzare il comando bc anche in modo non interattivo, utilizzando un file per dare i comandi in input.

Generare un file contentente il testo 2 + 3 utilizzando il comando
$ echo "2 + 3" > file.txt
Controllare il contenuto inserito utilizzando il comando cat. Utilizzarlo come input per il comando bc, dando il comando
$ bc < file.txt
Lo stesso risultato si sarebbe potuto ottenere senza bisogno di un file ausiliario componendo l'output il comando echo "2 + 3", che stampare la stringa 2 + 3, con l'input del comando bc. Questo si ottiene con il comando
$ echo "2 + 3" | bc

Si provi ad inventare degli esempi più interessanti.