Lezione ed Esercizi: Introduzione alla shell di Linux
Scopo principale di questa lezione è di prendere familiarità con la shell di Linux.
Il terminale e la shell
Oggigiorno la maggior parte degli utenti interagisce col computer tramite una interfaccia grafica, basata su menù, finestre e mouse. Una interfaccia di questo tipo si chiama GUI (Graphical User Interface). Ma prima che le interfacce grafiche si diffondessero (diciamo, fino ai primi anni '90) era molto più comune interagire con i computer tramite una interfaccia puramente testuale: l'utente scriveva dei comandi secondo una sintassi specifica, e il computer rispondeva, poi si metteva in attesa di un altro comando. Questo tipo di interfaccia prende il nome di CLI (Command Line Interface).
Il terminale
Sebbene la CLI sia oggi poco usata, tutti i sistemi operativi dispongono di un programma di emulazione terminale, che consente di interagire con il computer secondo il vecchio stile. Il nome esatto di questo programma dipende dal sistema operativo:
- Windows: Command Prompt e Windows PowerShell (anche Windows Terminal nelle nuove versioni di Windows)
- macOS: Terminal
- Linux (con interfaccia GNOME): Terminal, accessibile dal menù Applications → Utilities → Terminal
All'interno del programma di emulazione terminale è possibile eseguire vari programmi che non necessitano (e non sanno come utilizzare) l'interfaccia grafica. La maggior parte dei programmi che scriveremo noi gireranno all'interno dell'emulatore di terminale. In questo momento, però, il programma che ci interessa maggiormente eseguire all'interno del terminale è la shell.
La shell
Il terminale è solo il programma grafico che permette di interagire con il computer tramite comandi testuali. Il vero programma che esegue i comandi si chiama shell. In generale, ogni sistema operativo può avere più di una shell, ma di solito le più comuni sono:
- Windows: Command Prompt e PowerShell
- Linux: bash (Bourne-Again SHell)
- macOS: zsh (Z shell)
Questo è un esempio di bash in esecuzione su Linux:

A parte l’aspetto grafico, i comandi supportati da una shell cambiano molto da un sistema operativo ad un altro. Ad esempio, il comando per visualizzare il contenuto di una cartella è:
- Command prompt:
dir
- PowerShell:
dir
oppurels
- bash (Linux):
ls
- zsh (macOS):
ls
In generale:
- bash e zsh hanno comandi simili;
- PowerShell è abbastanza diversa ma ha alcuni comandi simili a bash/zsh;
- Command Prompt è completamente diverso (e anche oltraggiosamente limitato).
Noi studieremo la bash perché è quella standard di Linux, installata nei computer dell'aula informatica.
Vantaggi della shell
Una volta, prima dell'avvento delle interfacce grafiche, la shell era l'unico mezzo per comunicare con il sistema operativo. Oggi non è più così, ma la shell, per chi la sa usare, conserva ancora dei vantaggi rispetto all'interfaccia grafica:
- per la maggior parte dei compiti, è più veloce dare un comando con la shell che aprire finestre e finestrelle, anche perché non bisogna mai spostare le mani dalla tastiera per raggiungere il mouse;
- è programmabile: la shell è un vero e proprio linguaggio di programmazione con il quale è possibile automatizzare l'esecuzione di vari compiti;
- alcune attività di basso livello richiedono l'uso della shell, persino in ambiente Windows;
- è facilmente utilizzabile da un computer remoto, e in questo modo si ha l'accesso totale alla macchina, che può essere amministrata senza bisogno di essere presenti fisicamente nello stesso luogo.
I primi comandi della shell
Da questo punto della lezione, ci concentreremo sull'uso della shell in Linux.
Non appena lanciate l'applicazione Terminal, appare una finestra con una scritta simile a amato@ai-01:~$
, seguita da un blocco quadrato lampeggiante. La scritta prende il nome di prompt mentre il blocco lampeggiante è il cursore. Il prompt vi da alcune informazioni:
gamato
: è il nome del'utente che sta usando la shell, e corrisponde (di solito) al nome utente con cui avete fatto il login.ai-01
: è il nome del computer; i computer in aula informatica si chiamanoai-nn
, dovenn
è un numero che trovate stampato sul case.~
: indica quale è la cartella corrente (torneremo su questo tra un po').$
: indica che state operando come un utente normale. Se foste invece un super-utente, dotato di privilegi particolari per l'amministrazione di sistema, il$
sarebbe sosituito da#
.
Dal prompt è possibile digitare i comandi che si vogliono inviare al sistema, utilizzando anche i tasti standard per l'editing: Canc, Ins, Back, Inizio, Fine, ←, →. I tasti ↑ e ↓ consentono invece di scorrere i comandi già immessi precedentemente, che possono poi essere modificati. Non è possibile usare il mouse per spostare il cursore dentro la finestra del terminale: il mouse lo si può usare solo per selezionare un porzione di testo ai fini delle operazioni di copia e incolla. Una volta che un comando è stato scritto, si deve premere il tasto Invio perché esso venga accettato ed eseguito.
Uno dei comandi più utilizzati con la shell è ls
(abbreviazione di LiSt). Il comando ls
visualizza il contenuto della cartella corrente:
gamato@ai-01:~$ ls AndroidStudioProjects Desktop Downloads knime-workspace Music Pictures Public snap Videos compito.pdf Documents Hello.py lezione note-231113.txt problemi-upgrade.txt R Templates xrandr
Quelle in azzurro sono cartelle, quelle in nero dei file veri e propri. Esattamente gli stessi file e cartelle li vedete se aprite l'applicazione Files della GUI (Applications → Accessories → Files). La GUI e la CLI non sono due mondi separati, ma due modi diversi di accedere agli stessi dati. Questo è il risultato:
Se il comando viene scritto in maniera errata, si genera un errore:
gamato@ai-01:~$ lss Command 'lss' not found, but there are 15 similar ones.
È possibile visualizzare il contenuto di un file con il comando cat
(che non ha niente a che fare con i gatti, è l'abbreviazione di conCATenate). Il comando cat
ha bisogno però di un parametro, ovvero del nome del file da visualizzare. Il parametro va scritto dopo il comando, separato da spazi. Ad esempio:
gamato@ai-01:~$ cat Hello.py print("Hello world.")
La riga print("Hello world.")
è il contenuto del file Hello.py
. Potete aprire il file anche dalla GUI e vedrete che il contenuto è lo stesso. Ovviamente se il nome del file è sbagliato il sistema dà un errore. In particolare, bisogna stare attenti a scrivere maiuscole e minuscole in maniera corretta, perché per la shell di Linux una lettera minuscola e la corrispondente maiuscola sono due caratteri completamente diversi. Ad esempio il comando cat hello.py
fallisce:
gamato@ai-01:~$ cat hello.py cat: hello.py: No such file or directory
Notare che non tutti i file posono essere visualizzati con cat
, solo i cosiddetti file di testo, ovvero file che contengono unicamente testo senza nessun tipo di formattazione. Sono file di testo, ad esempio, i codici sorgente in qualunque linguaggio di programmazione e i file creati con programmi come Text Editor in Linux o Notepad in Windows. Non sono file di testo, ad esempio, documenti in formato Microsoft Office o LibreOffice ed i file PDF.
Se proviamo a visualizzare il contenuto del file compito.pdf
con cat
otteniamo qualcosa di incomprensibile:
gamato@ai-01:~$ cat compito.pdf %PDF-1.5 %���� 3 0 obj ... e tante altre linee omesse ...
È possibile creare un file vuoto dalla shell con il comando touch FILE
. Ad esempio:
gamato@ai-01:~$ ls AndroidStudioProjects Desktop Downloads knime-workspace Music Pictures Public snap Videos compito.pdf Documents Hello.py lezione note-231113.txt problemi-upgrade.txt R Templates xrandr gamato@ai-01:~$ touch prova gamato@ai-01:~$ ls AndroidStudioProjects Desktop Downloads knime-workspace Music Pictures prova R Templates xrandr compito.pdf Documents Hello.py lezione note-231113.txt problemi-upgrade.txt Public snap Videos gamato@ai-01:~$ cat prova
gamato@ai-01:~$
Notare che il file prova
compare solo nell'output del secondo comando ls
, quello dopo il comando touch
. Il comando cat
non dà errore, ma non visualizza nulla perché il file esiste ma è vuoto. Ovviamente ci sono anche modi per riempire un file con dei contenuti dalla CLI, ma non li vedremo: per questo useremo sempre un programma con interfaccia grafica.
Se vogliamo cancellare un file possiamo usare il comando rm FILE
(ReMove):
gamato@ai-01:~$ rm prova gamato@ai-01:~$ ls AndroidStudioProjects Desktop Downloads knime-workspace Music Pictures Public snap Videos compito.pdf Documents Hello.py lezione note-231113.txt problemi-upgrade.txt R Templates xrandr
Notare che il comando rm
è silenzioso, non visualizza nulla, ma ha effettivamente cancellato il file prova
, che infatti non compare più nell'elenco dei file.
Se vogliamo copiare un file creandone un duplicato, possiamo usare il comando cp
SOURCE DEST
(CoPy), che crea un copia del file SOURCE
chiamandolo DEST
. Se il file DEST
esiste già, esso viene rimpiazzato dalla copia di SOURCE
. Ad esempio:
gamato@ai-01:~$ cp Hello.py ciao.py gamato@ai-01:~$ ls AndroidStudioProjects Desktop Hello.py Music problemi-upgrade.txt snap xrandr ciao.py Documents knime-workspace note-231113.txt Public Templates compito.pdf Downloads lezione Pictures R Videos gamato@ai-remote:~$ cat ciao.py print("Hello world.")
Vedete che il comando cp
ha creato il file ciao.py
, con lo stesso contenuto di Hello.py
. Se invece vogliamo cambiare nome ad un file, possiamo usare il comando mv SOURCE DEST
(MoVe) che cambia il nome del file da SOURCE
a DEST
. Ad esempio
gamato@ai-01:~$ mv ciao.py ciriciao.py gamato@ai-01:~$ ls AndroidStudioProjects Desktop Hello.py Music problemi-upgrade.txt snap xrandr ciriciao.py Documents knime-workspace note-231113.txt Public Templates compito.pdf Downloads lezione Pictures R Videos
Vedete che dopo l'esecuzione del comando mv
il file ciao.py
non esiste più, perché il suo nome è cambiato in ciriciao.py
.
Comandi e opzioni
A molti dei comandi visti finora è possibile aggiungere delle opzioni per alterarne il funzionamento. Ad esempio, ls
può prendere come argomento i seguenti parametri (e tanti altri che qui non cito):
-a
: visualizza tutti i file, anche quelli nascosti. In Linux un file nascosto è un file che inizia con il punto (a
sta per all)-l
: visualizza, per ogni file, un dettaglio dei suoi attributi (lunghezza in byte, data di ultima modifica e informazioni sui diritti di accesso al file) (l
sta per long)
Quelle che abbiamo visto qua sopra sono le opzioni corte. Esse hanno tutte la stessa forma: il segno meno seguito da una lettera. Alcuni programmi supportano anche delle opzioni lunghe. Ad esempio per ls
abbiamo:
--all
: equivalente a-a
--help
: visualizza una spiegazione succinta del funzionamento dils
e di tutte le opzioni previste.--version
: visualizza la versione del programmals
.
Le opzioni possono essere combinate tra di loro. Ad esempio ls -a -l
visualizza tutti i file, compresi quelli nascosti, e visualizza per ognuno i suoi attributi. Stesso risultato dà ls --all -l
. Un altro modo di combiare le opzioni corte è usare un unico simbolo -
e, in sequenza, le lettere corrispondenti alle varie opzioni. Ad esempio ls -al ha lo stesso effetto di ls -a -l
.
Nota. Le opzioni --help
e --version
sono comuni a molti programmi.
Facciamo qualche esempio. Usiamo ls -a
per visualizzare il contenuto della cartella home, compresi tutti i file nascosti:
gamato@ai-01:~$ ls -a . Documents Hello.py Pictures Videos .. .dotnet .ipython .pki .vscode .adobe Downloads .JASP problemi-upgrade.txt .wine .android .eclipse .java .profile .wireshark AndroidStudioProjects .emacs.d .knime Public .Xauthority .aptitude .emulator_console_auth_token knime-workspace .purple .xchat2 .attach_pid40209 .equo .lesshst .python_history .xorgxrdp.10.log .....omissis.......
Abbiamo troncato l'output perché è troppo lungo. Vedete però che ci sono tantissimi file nascosti. Nella cartella home questo è normale, perché i file (e le cartelle) nascosti contengono la configurazione dei programmi che utilizzate.
Con ls -l
otteniamo invece questo risultato: non ci sono i file nascosti, ma i nomi dei file compaiono adesso uno per riga, e ognuno è accompagnato da varie informazioni,
total 868 drwxrwxr-x 10 gamato gamato 4096 ott 1 2023 AndroidStudioProjects -rw-rw-r-- 1 gamato gamato 22 set 21 00:23 ciriciao.py -rw-rw-r-- 1 gamato gamato 189728 set 20 18:22 compito.pdf drwxr-xr-x 2 gamato gamato 4096 set 11 11:58 Desktop drwxr-xr-x 3 gamato gamato 4096 set 14 23:42 Documents drwxr-xr-x 2 gamato gamato 4096 set 11 11:04 Downloads -rw-rw-r-- 1 gamato gamato 22 set 20 13:03 Hello.py drwxrwxr-x 4 gamato gamato 4096 feb 20 2023 knime-workspace drwxrwxr-x 2 gamato gamato 4096 set 20 15:09 lezione drwxr-xr-x 2 gamato gamato 4096 set 28 2022 Music -rw-rw-r-- 1 gamato gamato 569 nov 13 2023 note-231113.txt drwxr-xr-x 4 gamato gamato 4096 mag 13 17:05 Pictures -rw-rw-r-- 1 gamato gamato 623379 giu 14 19:23 problemi-upgrade.txt drwxr-xr-x 2 gamato gamato 4096 ott 1 2023 Public drwxrwxr-x 3 gamato gamato 4096 feb 23 2020 R drwx------ 7 gamato gamato 4096 feb 9 2023 snap drwxr-xr-x 2 gamato gamato 4096 set 28 2022 Templates drwxr-xr-x 3 gamato gamato 4096 gen 5 2023 Videos -rw-r--r-- 1 gamato gamato 106 nov 28 2022 xrandr
Cosa è il significato di tutte queste colonne ?
- Il primo carattere in ogni riga indica il tipo di file. Trovate
d
per una directory,-
per un file standard. Ci sono altri tipi di file, sebbene poco comuni. - I restanti caratteri
rwx-
indicano i diritti di accesso al file (quali utenti possono accedere a quel file). Tralasciamo questo argomento perché non è al momento di nostro interesse. - Il primo dei due
gamato
è l'utente proprietario del file. - Il secondo dei due
gamato
è il gruppo proprietario del file. Tralasciamo questo argomento perché non è al momento di nostro interesse - Il numero successivo è la lunghezza del file in byte.
- La colonna successiva è la data di ultima modifica del file.
- L'ultima colonna è il nome del file.
Questo è il riassunto della situazione:
Esercizio 1
Si impara solo sperimentando. Scaricate i file Hello.py e compito.pdf. Se non sono già nella cartella home, spostateli lì usando l'interfaccia grafica. Quindi lanciate il terminale e leggete la sezione "I primi comandi della shell" qui sopra, provando a ripetere in prima persona gli esempi forniti di comandi per la shell.
Cartelle e loro gestione
La memoria di massa di un computer è, come quella principale, una sequenza di byte. Essa è però organizzata in unità più piccole, chiamate file. I file sono a loro volta organizzati in cartelle (in inglese folder o directory), a formare una struttura (chiamata albero) che parte da una directory principale o directory radice e prosegue per varie sotto-directory. Questa ad esempio è un estratto della struttura ad albero di un sistema Linux in aula informatica.
Per avere accesso a directory e file presenti nel computer basta lanciare l'applicazione Files. Quella che viene aperta di default è la home directory dell'utente. Ogni utente ha una home directory, che può gestirsi come vuole, e dove può salvare tutti i propri dati. Modifiche alla propria home directory non influenzano le home directory degli altri utenti. Nei sistemi in stile Unix di solito le home directory si trovano all'interno della directory home
. In particolare, in aula informatica, le home directory si trovano dentro la cartella labeconomia
, che sta a sua volta dentro la cartella home.
Per uscire dalla home directory e portarsi sulla directory radice, si può cliccare su Other Locations nella barra a sinistra in basso dell'applicazione Files e poi su Computer. Questa è la directory radice vista dall'applicazione Files.
Vediamo ora alcuni comandi per manipolare le cartelle da linea di comando. Nella shell c'è un concetto di directory corrente, che è quella su cui operano i vari comandi. Normalmente la directory corrente è la propria home, che nel prompt è indicata convenzionalmente dal simbolo ~
(tilde). Se vogliamo sapere veramente qual è la cartella corrente nell'albero delle directory, si può usare il comando pwd
(Print Working Directory):
gamato@ai-01:~$ pwd /home/labeconomia/gamato
La scritta /home/labeconomia/gamato
indica la cartella a cui si arriva partendo la radice ed entrando successivamente nella cartella home
, poi nella cartella labeconomia
, infine nella cartella gamato
.
Il comand mkdir
DIRECTORY
(MaKe DIRectory) crea una nuova cartella all'interno della cartella corrente.
gamato@ai-01:~$ mkdir myfolder gamato@ai-01:~$ ls AndroidStudioProjects Desktop Hello.py Music problemi-upgrade.txt snap xrandr myfolder Documents knime-workspace note-231113.txt Public Templates compito.pdf Downloads lezione Pictures R Videos
Possiamo a questo punto entrare nella cartella myfolder usando il comando cd
DIRECTORY
(Change Directory):
gamato@ai-01:~$ cd myfolder gamato@ai-01:~/myfolder$
Vedete che dopo il comando cd
il prompt è cambiato: dove prima c'era solo la tilde, ad indicare la home directory, adesso c'è ~/myfolder
ad indicare che la cartella corrente è la cartella myfolder
che si trova dentro la home directory. Se diamo il comando ls
, non avendo mai messo nulla dentro questa cartella, non otteniamo nulla:
gamato@ai-01:~/myfolder$ ls gamato@ai-01:~/myfolder$ touch pippo gamato@ai-01:~/myfolder$ ls pippo
Se vogliamo salire di un ramo nell'albero delle directory, si può usare la sintassi speciale cd ..
(cd
seguito da due caratteri punto).
gamato@ai-01:~/myfolder$ cd .. gamato@ai-01:~$ ls AndroidStudioProjects Desktop Hello.py Music Pictures R Videos ciriciao.py Documents knime-workspace myfolder problemi-upgrade.txt snap xrandr compito.pdf Downloads lezione note-231113.txt Public Templates
Notare che c'è un altro modo per visualizzare il contenuto di una cartella senza bisogno di entrarci dentro, che è tramite il comando ls con un parametro aggiuntivo che specifica la cartella da visualizzare:
gamato@ai-01:~$ ls myfolder/ pippo
Per cambiare nome ad una cartella possiamo usare lo stesso comando mv
visto per i file:
gamato@ai-01:~$ mv myfolder miacartella gamato@ai-01:~$ ls AndroidStudioProjects Desktop Hello.py miacartella Pictures R Videos ciriciao.py Documents knime-workspace Music problemi-upgrade.txt snap xrandr compito.pdf Downloads lezione note-231113.txt Public Templates
Vedete che la cartella myfolder
è ora diventata miacartella
.
È possibile anche copiare una cartella creandone un duplicato usando il comando cp
con l'opzione -r
(che sta per recursive, un termine che impareremo a conoscere):
gamato@ai-01:~$ cp -r miacartella miacartella2
gamato@ai-01:~$ ls
AndroidStudioProjects Desktop Hello.py miacartella note-231113.txt Public Templates
ciriciao.py Documents knime-workspace miacartella2 Pictures R Videos
compito.pdf Downloads lezione Music problemi-upgrade.txt snap xrandr
gamato@ai-01:~$ ls miacartella
pippo
gamato@ai-01:~$ ls miacartella2
pippo
Infinte, se si vuole cancellare una cartella, si può usare il comando rmdir CARTELLA
(ReMove DIRectory). È importante però che la CARTELLA
sia vuota, altrimenti il comando fallisce.
gamato@ai-remote:~$ rmdir miacartella2
rmdir: failed to remove 'miacartella2': Directory not empty
gamato@ai-remote:~$ ls miacartella2
pippo
gamato@ai-remote:~$ rmdir miacartella2
rmdir: failed to remove 'miacartella2': Directory not empty
gamato@ai-remote:~$ cd miacartella2
gamato@ai-remote:~/miacartella2$ ls
pippo
gamato@ai-remote:~/miacartella2$ rm pippo
gamato@ai-remote:~/miacartella2$ cd ..
gamato@ai-remote:~$ rmdir miacartella2
gamato@ai-remote:~$ ls
AndroidStudioProjects Documents knime-workspace Music problemi-upgrade.txt snap xrandr
compito.pdf Downloads lezione note-231113.txt Public Templates
Desktop Hello.py miacartella Pictures R Videos
Le cartelle speciali . e ..
Se visualizziamo tutti i file presenti in una cartella con ls -a
vedremo che troviamo sempre due cartelle speciali. Questo ad esempio è il contenuto della directory miacartella
.
gamato@ai-01:~$ cd miacartella
gamato@ai-01:~/miacartella$ ls -a . .. pippo
La cartella .
(punto) indica la cartella visualizzata (ovvero miacartella
), mentre ..
indica la cartella da cui si proviene nell'albero delle directory (ovvero la cartella home). Pertanto, il comando cd .
non ha assolutamente alcun effetto (rimane nella cartella corrente), mentre cd ..
risale l'albero delle directory, come già visto.
gamato@ai-01:~/miacartella$ cd . gamato@ai-01:~/miacartella$ cd .. gamato@ai-01:~$
Esercizio 2
Vi ripeto che si impara solo sperimentando. Leggete la sezione "Cartelle e loro gestione" qui sopra, provando a ripetere in prima persona gli esempi forniti di comandi per la shell.
Percorsi assoluti e relativi
Abbiamo visto che molti comandi hanno come argomento un nome di file. Ma che struttura ha un nome di file Linux? Nel vecchio sistema operativo DOS, il nome aveva una struttura fissa di 8 caratteri, un punto, e altri 3 caratteri (detti estensione). L'estensione serviva a identificare il tipo di file: .jpg
per file immagini JPEG, .txt
per file di testo puri, .doc
per file Word, etc..
Nei sistemi operativi moderni un nome di file è una stringa di caratteri qualunque, e può contenere quanti punti si desidera (anche nessuno). L'estensione non è necessaria, ma spesso la si aggiunge per facilitare la vita all'utilizzatore del computer, che così è in grado di riconoscere il tipo di ogni file. Anche alcuni programmi si basano sull'estensione di un file per decidere come trattarlo. Notare che ormai l'estensione può anche essere più lunga di 3 caratteri: ad esempio .java
è l'estensione standard per i file sorgente Java.
Tuttavia, specificare semplicemente il nome di un file non è sufficiente. Infatti, all'interno del file system possono esserci molti file con lo stesso nome, ma che stanno in directory diverse. Come si fa, allora, a indicare con esattezza un file specifico, in modo che non sorgano ambiguità? Bisogna utilizzare i pathname (nomi dei percorsi) che possono essere di due tipi: assoluti o relativi.
Percorso assoluto
Un percorso assoluto è una stringa del tipo:
/DIRECTORY/DIRECTORY/DIRECTORY/FILE
che inizia con la barra di divisione, ha una serie di componenti separati da barre e termina con un nome di file. La sequenza delle varie componenti DIRECTORY
è la sequenza di cartelle dentro le quali il sistema deve entrare, partendo dalla radice, per raggiungere la cartella dove si trova il file
desiderato. Ad esempio:
/home/amato/prova.txt
si riferisce a un fileprova.txt
nella home directory digamato
./abcd
si riferisce a un file di nome abcd (senza estensione) dentro la directory radice.
Sono importanti alcune cose:
- il percorso assoluto deve iniziare con la barra di divisione;
- la barra da utilizzare è quella per la divisione (/) e non la barra retroversa (\) che si usa invece nei sistemi Windows;
- è necessario specificare la sequenza completa di tutte le directory da attraversare per arrivare al file desiderato.
Percorso relativo
Ogni processo (programma in esecuzione) in Linux ha una directory corrente. Quando si specifica un nome di file direttamente, senza percorso, il file viene cercato in questa directory. Abbiamo visto che per cambiare directory corrente nella shell di Linux, si può usare il comando cd
. Più in generale, la directory corrente serve come punto di riferimento per i percorsi relativi.
Un percorso relativo è una stringa di questo tipo:
DIRECTORY/DIRECTORY/DIRECTORY/FILE
quindi è simile a un percorso assoluto ma non ha la barra iniziale. Anche il significato è simile a quello di un percorso assoluto, con la differenza che la directory da cui iniziare la ricerca del file non è la directory radice ma la directory corrente. Ad esempio, se la directory corrente è /home
, allora:
amato/prova.txt
si riferisce a un fileprova.txt
nella home directory diamato
.../abcd
si riferisce a un file di nome abcd (senza estensione) dentro la directory radice.
Di solito ovunque si può inserire il nome di un file, si può inserire un percorso assoluto o relativo. Ma quale conviene usare tra i due? Quando si usa la shell in maniera interattiva, come facciamo noi in questa lezione, si può usare quello che ci torna più comodo. Quando però si scrivono dei programmi che hanno bisogno di accedere a vari file ad essi correlati, è meglio utilizzare percorsi relativi. In questo modo, sarà poi più facile spostare tutto il software da una directory ad un altra senza comprometterne il funzionamento.
Ad esempio, supponiamo di aver scritto un programma vis
che ha bisogno di alcune immagini per funzionare. Decidiamo di mettere il programma vis nella directory /home/amato/prg
e le immagini in una sottodirectory, ad esempio /home/amato/prg/img
. Quando nel programma abbiamo bisogno di riferirci ad una immagine, è meglio se usiamo un percorso relativo alla directory /home/amato/prg
. Così, l'immagine titolo.jpg
dovrà essere riferita con il percorso img/titolo.jpg
. In questo modo, quando ci porteremo il programma a casa nel nostro computer, potremo decidere di mettere il tutto (il programma vis
e la sottodirectory img
) nella directory /usr/local/mioprog
e il programma continuerà a funzionare a dovere. La vecchia immagine /home/amato/prg/img/titolo.jpg
non esiste più, ma al suo posto abbiamo /usr/local/mioprog/img/titolo.jpg
e, partendo da /usr/local/mioprog
il percorso relativo img/titolo
.jpg punta propro a quest'ultima. Torneremo su questo punto quando vedremo come manipolare i file dal linguaggio Python.
Operare con percorsi assoluti e relativi dalla CLI
Nei comandi della CLI, tutte le volte che compare un nome di file si può invece mettere un percorso assoluto o relativo.
Ad esempio il comando cp Hello.py miacartella/Ciao.py
copia il file Hello.py
che si trova nel file Ciao.py
dentro la cartella miacartella
.
gamato@ai-01:~$ cp Hello.py miacartella/Ciao.py gamato@ai-01:~$ cat miacartella/Ciao.py print("Hello world.")
Se nel percorso destinazione si omette il nome del file, esso viene copiato con lo stesso nome che aveva nella cartella originaria.
gamato@ai-01:~$ cp Hello.py miacartella gamato@ai-01:~$ ls miacartella Ciao.py Hello.py pippo
Vediamo che in miacartella
si trovano tre file: pippo
(creato inizialmente con il comando touch
), Ciao.py
(copiato prima) e Hello.py
(copiato adesso). Analogamente si può usare il comando mv
per spostare un file da una cartella ad un'altra:
gamato@ai-remote:~$ ls AndroidStudioProjects Desktop Hello.py miacartella note-231113.txt Public Templates ciriciao.py Documents knime-workspace miacartella2 Pictures R Videos compito.pdf Downloads lezione Music problemi-upgrade.txt snap xrandr gamato@ai-remote:~$ mv ciriciao.py miacartella gamato@ai-remote:~$ ls AndroidStudioProjects Documents knime-workspace miacartella2 Pictures R Videos compito.pdf Downloads lezione Music problemi-upgrade.txt snap xrandr Desktop Hello.py miacartella note-231113.txt Public Templates gamato@ai-remote:~$ ls miacartella Ciao.py ciriciao.py Hello.py pippo
Si vede che col comando mv il file Hello.py
è sparito dalla cartella home ed è stato spostato in miacartella
.
Esercizio 3
Si consideri la seguente struttura ad albero:
Scrivere i percorsi relativi ed assoluti per i file f1
, f2
, f3
e per le directory atena
e zeus
, nei due casi in cui la directory corrente è opt
o atena
.
Varie ed eventuali
Comandi e programmi
La maggior parte di quelli che abbiamo chiamato comandi della shell sono in realtà programmi veri e propri che la shell si limita a lanciare. Ad esempio, cp
è un programma, il cui percorso completo è /usr/bin/cp
. Dalla shell è possibile lanciare non solo i comandi, ma anche programmi più sofisticati e con interfaccia grafica. Ad esempio, se si vuole modificare il file Hello.py
, è possibile apririle dalla GUI, ma in alternativa è possibile lanciare dalla shell l'editor di testo fornendo come parametro il nome del file da modificare. Ad esempio:
gamato@ai-01:~$ gedit Hello.py
In questo comando gedit
è l'editor per file di testo standard di Linux (un po' come il Notepad di Windows). La shell chiama il programma gedit che quindi apre una finestra grafica con il contenuto del file specificato. Notare che la shell è sospesa, non accetta più nessun input, finché il programma gedit
è in esecuzione.
Completamento automatico
Una caratteristica utile della shell di Linux è il completamente automatico. In varie circostante potete premere il tasto Tab e la shell completa quello che state scrivendo nella maniera più ovvia. Il tasto Tab (tabulazione) si trova quasi sempre a sinistra, sotto la barra retroversa (\
), e su di esso sono disegnate due frecce puntate in direzioni opposte. Ad esempio, se siete nella situazione
gamato@ai-01:~$ pass
e premete Tab, la stringa pass
viene completata in passwd
(il comando per cambiare la propria password). Questo perché passwd
è l'unico comando che inizia con pass. Analogamente, se nella directory corrente c'è il file "Hello.py
" e voi premete Tab quando avete digitato
gamato@ai-01:~$ cat He
allora He
viene completato in Hello.py
. In generale, quasi su ogni sistema è vero quanto segue:
- se premete Tab; sulla prima parola di una riga di comando, la shell tenta di completare la stringa immessa con un comando valido;
- se premete Tab sulle parole successive alla prima in una riga di comando, la shell tenta di completare la stringa con un nome di file valido.
Talvolta premendo Tab non succede niente: vuol dire che c'è ambiguità nel modo in cui si può completare la stringa. Ad esempio, se abbiamo anche il file Herr
oltre a Hello.py
, premere Tab dopo He
è ambiguo perché He
potrebbe essere completato in due modi diversi.
In questo caso, si può premere Tab due volte di seguito per avere l'elenco dei possibili completamenti. Ad esempio, con
gamato@ai-01:~$ rm
premendo TabTab si ha l'elenco dei comandi che iniziano con rm:
gamato@ai-remote:~$ rm rm rmdir rmic rmid rmiregistry rmmod rmt rmt-tar
Il Tab può essere usato per spostarsi velocemente nell'albero delle directory. Se si vuole visualizzare il file /proc/cpuinfo
(che contiene informazioni sulla CPU usata dal computer) il comando da dare è cat /proc/cpuinfo
. Si può scrivere questo comando molto più velocemente digitando:
cat /pTab/cpTab
La funzione di completamento automatico è veramente comoda. Una volta che ci si è famirializzato, è difficile farne a meno.
Nomi dei file con spazi
Se un nome dei file contiene uno spazio, e lo si deve specificare nella shell, va racchiuso tra apici o virgolette, altrimenti la shell pensa che si tratti di due file diversi. Ad esempio, se si vuole creare un file vuoto dal nome Galileo Galiei
non si può usae il comando touch Galileo Galilei
, perché questo creerebbe due file: uno di nome Galileo
, l'altro di nome Galilei
. Il comando corretto da usare è touch 'Galileo Galilei'
.
Immissione caratteri speciali
Spesso è necessario inserire dei caratteri che non sono presenti nella tastiera. Come si fa in questo caso? Il trucco tipico di Windows (Alt+il codice ASCII sul tastierino numerico) su Linux non funziona. In realtà, i caratteri più comuni possono essere digitati con alcune combinazioni di tasti standard:
- AltGr + apostrofo = apice
- AltGr + ì = ~
- AltGr + e = €
- AltGr + é = Shift + AltGr + è = {
- AltGr + * = Shift + AltGr + più = }
Per chi non lo sapesse, il tasto Shift è quello che si usa per fare le maiuscole, tavolta indicato con Maiusc nelle tastiere italiane, mentre AltGr è il tasto Alt posto a destra della barra spaziatrice.
Un'altra combinazione da sapere è quella per copiare e incollare nel terminale. Mentre di solito le combinazione per copiare e incollare sono Ctrl + C e Ctrl + V rispettivamente, queste combinazioni non funzionano nel terminale perché hanno un altro significato. Al loro posto, è possibile usare Ctrl + Maiusc + C e Ctrl + Maiusc + V.
Il manuale in linea
Nessuno è ingrado di ricordare tutti i possibili comandi e le differenti opzioni disponibili in ambiente Unix. Per fortuna la documentazione in materia è estensiva. Abbiamo già visto l'opzione --help
che è possibile fornire a molti comandi per farci restituire la spiegazione del suo funzionamento e delle opzioni che supporta. La spiegazione che si ottiene è però spesso troppo stringata, utile quando il comando lo si conosce già e semplicemente non ci si ricorda il formato di qualche opzione, ma non quando si vuole imparare come utilizzarlo.
Per quest'ultimo scopo è molto più utile il comando man COMANDO
(manual). Ad esempio, esempio man rmdir
visualizza il manuale del comando rmdir
, che vedete qui sotto:
RMDIR(1) User Commands RMDIR(1) NAME rmdir - remove empty directories SYNOPSIS rmdir [OPTION]... DIRECTORY... DESCRIPTION Remove the DIRECTORY(ies), if they are empty. --ignore-fail-on-non-empty ignore each failure that is solely because a directory is non-empty -p, --parents remove DIRECTORY and its ancestors; e.g., 'rmdir -p a/b/c' is similar to 'rmdir a/b/c a/b a' -v, --verbose output a diagnostic for every directory processed --help display this help and exit --version output version information and exit AUTHOR Written by David MacKenzie. REPORTING BUGS GNU coreutils online help: <https://www.gnu.org/software/coreutils/> Report any translation bugs to <https://translationproject.org/team/>
La lettura del manuale non è sempre agevole e bisogna abituarsi un po', anche perché spesso le spiegazioni sono molto tecniche. Le sezioni più importanti sono:
- NAME: il nome del comando e una sua descrizione breve (che sta in una sola riga)
- SYNOPSIS: la sintassi del comando. È importante conoscere alcune convenzioni utilizzate in questa sezione.
- I tre puntini (
...
) stanno ad indicare che il parametro precedente può essere ripetuto più volte (separando i vari elementi da spazio). Quindi, se voglio cancellare le cartellec1
ec2
, posso dare il comandormdir c1 c2
. - Quello che sta tra parentesi quadre è opzionale: si può mettere, ma non è necessario. La parentesi quadre stesse non vanno mai inserite nel comando ! Quindi la stringa
[OPTION]...
vuol dire che dopo il nome del comando è possibile, facoltativamente, indicare una o più opzioni. Notare che invece almeno una directory deve essere presente perché il parametroDIRECTORY
non è racchiuso tra parentesi quadre. Ad esempio, il comandormdir -p c1/c2
cancella la cartellac2
(che si trova dentroc1
) e poic1
stessa (supponendo che per il resto queste due cartelle siano tutte vuote). Normalmente la cartellac1
non verrebbe cancellata, è l'opzione-p
che causa questo comportamento. - Alcune opzioni sono disponibili sia in forma breve che in forma lunga: le due forme vengono mostrate una accanto all'altra. Ad esempio, una alternativa a
rmdir -p c1/c2
èrmdir --parents c1/c2
.
- I tre puntini (
- DESCRIPTION: spiega cosa fa il comando e il significato di tutte le opzioni disponibili.
Esercizi riassuntivi
Esercizio 4
Visualizzare il contenuto del file /proc/cpuinfo
.
Esercizio 5
Esaminare l'elenco delle periferiche PCI presenti nel sistema eseguendo il programma lspci
.
Esercizio 6
Utilizzando i comandi della shell, creare all'interno della vostra home directory una cartella dal nome prova
e, dentro quest'ultima, una ulteriore cartella dal nome prova-nidificata
. Creare dentro prova-nidificata
un file di testo di nome provatesto.txt
con un contenuto a piacere (come editor di testi si può usare il programma Text Editor). Controllare che il contenuto sia leggibile usando il comando cat
. A questo punto spostare il file provatesto.txt
nella directory prova
con il nuovo nome provatesto2.txt
, e cancellare la directory prova-nidificata
.
Esercizio 7
Questo esercizio è da considerare la continuazione dell'esercizio precedente.
Creare la directory prova-nidificata2
dentro la directory prova
e prova-nidificata3
dentro prova-nidificata2
. Creare un file di testo prova-file
dentro prova-nidificata3
con un contenuto a piacere. Il metodo standard che abbiamo visto per cancellare unaa irectory dalla shell è quello di cancellare prima i file che essa contiene con rm
e poi la cartella stessa con rmdir
. Senza seguire questa procedura, consultare la documentazione sul comando rm
e capire come cancellare, con un unico comando, la directory prova
e tutte le sue sottodirectory.