Capitolo 15. Filtri, programmi e comandi esterni

Sommario
15.1. Comandi fondamentali
15.2. Comandi complessi
15.3. Comandi per ora/data
15.4. Comandi per l'elaborazione del testo
15.5. Comandi inerenti ai file e all'archiviazione
15.6. Comandi per comunicazioni
15.7. Comandi per il controllo del terminale
15.8. Comandi per le operazioni matematiche
15.9. Comandi diversi

I comandi standard UNIX rendono gli script di shell più versatili. La potenza degli script deriva dall'abbinare, in semplici costrutti di programmazione, comandi di sistema e direttive di shell.

15.1. Comandi fondamentali

I primi comandi che un principiante deve conoscere

ls

Il comando fondamentale per "elencare" i file. È molto facile sottostimare la potenza di questo umile comando. Per esempio, l'uso dell'opzione -R, ricorsivo, con ls provvede ad elencare la directory in forma di struttura ad albero. Altre utili opzioni sono: -S, per ordinare l'elenco in base alla dimensione, -t, per ordinarlo in base alla data di modifica, -b, per mostrare i caratteri di escape e -i per mostrare gli inode dei file (vedi Esempio 15-4).

Suggerimento

Il comando ls restituisce un exit status diverso da zero quando cerca di elencare un file inesistente.

bash$ ls abc
ls: abc: No such file or directory
				    
				    
bash$ echo $?
2

Esempio 15-1. Utilizzare ls per creare un sommario da salvare in un CDR

#!/bin/bash
# ex40.sh (burn-cd.sh)
# Script per rendere automatica la registrazione di un CDR.

VELOC=2           #  Potete utilizzare una velocità più elevata
                  #+ se l'hardware la supporta.
FILEIMMAGINE=cdimage.iso
CONTENUTIFILE=contenuti
DISPOSITIVO=cdrom
# DISPOSITIVO="0,0" Per le vecchie versioni di cdrecord
DEFAULTDIR=/opt   # Questa è la directory contenente i dati da registrare.
                  # Accertatevi che esista.
                  # Esercizio: aggiungente un controllo che lo verifichi.

# Viene usato il programma "cdrecord" di Joerg Schilling:
# http://www.fokus.fhg.de/usr/schilling/cdrecord.html

#  Se questo script viene eseguito da un utente ordinario va impostato
#+ il bit suid di cdrecord (chmod u+s /usr/bin/cdrecord, da root).
#  Naturalmente questo crea una falla nella sicurezza, anche se non rilevante.

if [ -z "$1" ]
then
  DIRECTORY_IMMAGINE=$DEFAULTDIR
  #  Viene usata la directory predefinita se non ne viene specificata
  #+ alcuna da riga di comando.
else
  DIRECTORY_IMMAGINE=$1
fi

#  Crea il "sommario" dei file.
ls -lRF $DIRECTORY_IMMAGINE > $DIRECTORY_IMMAGINE/$CONTENUTIFILE
#  L'opzione "l" fornisce un elenco "dettagliato".
#  L'opzione "R" rende l'elencazione ricorsiva.
#  L'opzione "F" evidenzia i tipi di file (le directory hanno una
#+ "/" dopo il nome).
echo "Il sommario è stato creato."

# Crea l'immagine del file che verrà registrato sul CDR.
mkisofs -r -o $FILEIMMAGINE $DIRECTORY_IMMAGINE
echo "È stata creata l'immagine ($FILEIMMAGINE) su file system ISO9660."

# Registra il CDR.
echo "Sto \"bruciando\" il CD."
echo "Siate pazienti, occorre un po' di tempo."
cdrecord -v -isosize speed=$VELOC dev=$DISPOSITIVO $FILEIMMAGINE

exit $?
cat, tac

cat è l'acronimo di concatenato, visualizza un file allo stdout. In combinazione con gli operatori di redirezione (> o >>) è comunemente usato per concatenare file.

# Usi di 'cat'
cat nomefile                          # Visualizza il contenudo del file.

cat file.1 file.2 file.3 > file.123   # Concatena tre file in uno.
L'opzione -n di cat numera consecutivamente le righe del/dei file di riferimento. L'opzione -b numera solo le righe non vuote. L'opzione -v visualizza i caratteri non stampabili, usando la notazione ^ . L'opzione -s comprime tutte le righe vuote consecutive in un'unica riga vuota.

Vedi anche Esempio 15-25 e Esempio 15-21.

Nota

In una pipe, risulta più efficiente redirigere lo stdin in un file piuttosto che usare cat.

cat nomefile | tr a-z A-Z

tr a-z A-Z < nomefile   #  Stesso risultato, ma si avvia un processo in meno,
                        #+ e senza dover usare la pipe.

tac è l'inverso di cat e visualizza un file in senso contrario, vale a dire, partendo dalla fine.

rev

inverte ogni riga di un file e la visualizza allo stdout. Non ha lo stesso effetto di tac poiché viene preservato l'ordine delle righe, semplicemente rovescia ciascuna riga (come l'immagine riflessa da uno specchio).

bash$ cat file1.txt
Questa è la riga 1.
Questa è la riga 2.


bash$ tac file1.txt
Questa è la riga 2.
Questa è la riga 1.


bash$ rev file1.txt
.1 agir al è atseuQ
.2 agir al è atseuQ
	      

cp

È il comando per la copia dei file. cp file1 file2 copia file1 in file2, sovrascrivendo file2 nel caso esistesse già (vedi Esempio 15-6).

Suggerimento

Sono particolarmente utili le opzioni -a di archiviazione (per copiare un intero albero di directory), -u di aggiornamento (che evita la sovrascrittura dei file più recenti aventi l'identico nome), e -r e -R di ricorsività.

cp -u dir_sotgente/* dir_destinazione
#  "Sincronizza" dir_destinazione con dir_sorgente
#+  copiando i file più recenti e quelli precedentemente inesistenti.

mv

È il comando per lo spostamento di file. È equivalente alla combinazione di cp e rm. Può essere usato per spostare più file in una directory o anche per rinominare una directory. Per alcune dimostrazioni sull'uso di mv in uno script, vedi Esempio 9-19 e Esempio A-2.

Nota

Se usato in uno script non interattivo, mv vuole l'opzione -f (forza) per evitare l'input dell'utente.

Quando una directory viene spostata in un'altra preesistente, diventa la sottodirectory di quest'ultima.

bash$ mv directory_iniziale directory_destinazione

bash$ ls -lF directory_destinazione
total 1
drwxrwxr-x    2 bozo  bozo      1024 May 28 19:20 directory_iniziale/
	      

rm

Cancella (rimuove) uno o più file. L'opzione -f forza la cancellazione anche dei file in sola lettura. È utile per evitare l'input dell'utente in uno script.

Nota

Il semplice comando rm non riesce a cancellare i file i cui nomi iniziano con un trattino.

bash$  rm -bruttonome
 rm: invalid option -- b
 Try `rm --help' for more information.

Un modo per riuscirci è far precedere il nome del file che deve essere rimosso da punto-barra.

bash$ rm ./-bruttonome
Un metodo alternativo è far precedere il nome del file da " -- ".
bash$ rm -- -bruttonome

Avvertimento

Se usato con l'opzione di ricorsività -r, il comando cancella tutti i file della directory corrente. Uno sbadato rm -rf * può eliminare buona parte della struttura di una directory.

rmdir

Cancella una directory. Affinché questo comando funzioni è necessario che la directory non contenga alcun file -- neanche gli "invisibili" dotfile [1].

mkdir

Crea una nuova directory. Per esempio, mkdir -p progetto/programmi/Dicembre crea la directory indicata. L'opzione -p crea automaticamente tutte le necessarie directory indicate nel percorso.

chmod

Modifica gli attributi di un file, o directory, esistente (vedi Esempio 14-12).

chmod +x nomefile
# Rende eseguibile "nomefile" per tutti gli utenti.

chmod u+s nomefile
#  Imposta il bit "suid" di "nomefile".
#  Un utente comune può eseguire "nomefile" con gli stessi privilegi del 
#+ proprietario del file (Non è applicabile agli script di shell).

chmod 644 nomefile
#  Dà al proprietario i permessi di lettura/scrittura su "nomefile", il 
#+ permesso di sola lettura a tutti gli altri utenti 
#  (modalità ottale).

chmod 444 nomefile
#  Dà a tutti gli utenti il permesso di sola lettura su "nomefile".
#  Non è consentito, ad un utente che non sia il proprietario del file, 
#+ (tranne che a root) di modificarlo (usando, per esempio, un editor di testo),
#+ e persino il suo proprietario deve forzarne il salvataggio
#+ in caso di modifica.
#  Le stesse limitazioni valgono per la cancellazione del file.

chmod 1777 nome-directory
#  Dà a tutti gli utenti i permessi di lettura, scrittura ed esecuzione nella
#+  directory, inoltre imposta lo "sticky bit". Questo significa che solo il 
#+ proprietario della directory, il proprietario del file e, naturalmente, root
#+ possono cancellare dei file particolari presenti in quella directory.

chmod 111 nome-directory
#  Dà a tutti gli utenti il permesso di sola esecuzione nella directory.
#  Questo significa che si possono eseguire e LEGGERE i file di quella 
#+ directory (il permesso di esecuzione implica necessariamente il permesso
#+ di lettura, perché: è impossibile eseguire un file senza essere
#+ in grado di leggerlo).
#  I file, però, non possono essere elencati o effettuarne la ricerca
#+ per mezzo del comando "find".
#  Queste limitazioni non valgono per root.

chmod 000 nome-directory
#  Nessun permesso sulla directory.
#  I suoi file non possono essere scritti, letti o eseguiti.
#  Non è neanche possibile elencarli o accedervi con "cd".
#  Si può, però, rinominare (mv) la directory
#+ o cancellarla (rmdir), se vuota.
#  È anche possibile effettuare dei link simbolici ai suoi file,
#+ ma anche tali link non possono essere scritti, letti o eseguiti.
#  Queste limitazioni non valgono per root

chattr

Modifica (change) gli attributi del file. Ha lo stesso effetto di chmod, visto sopra, ma con sintassi ed opzioni diverse, e funziona solo su un filesystem di tipo ext2.

Un'opzione particolarmente interessante di chattr è i. chattr +i nomefile contrassegna quel file come immodificabile. Il file non può essere in alcun modo modificato, soggetto a link o cancellato, neanche da root. Questo attributo può essere impostato o rimosso solo da root. In modo simile, l'opzione a contrassegna il file come scrivibile, ma solo per accodamento.

root# chattr +i file1.txt


root# rm file1.txt

rm: remove write-protected regular file `file1.txt'? y
rm: cannot remove `file1.txt': Operation not permitted
	      

Se un file ha impostato l'attributo s (secure), in caso di cancellazione il/i blocco/hi che occupava sul disco verrà/anno sovrascritto/i con degli zero.

Se un file ha impostato l'attributo u (undelete), in caso di cancellazione sarà ancora possibile recuperarne il contenuto (non cancellato).

Se un file ha impostato l'attributo c (compress), viene automaticamente compresso prima della scrittura su disco e decompresso per la lettura.

Nota

Gli attributi di un file impostati con chattr non vengono elencati (se si è usato ls -l).

ln

Crea dei link a file esistenti. Un "link" è un riferimento a un file, un nome alternativo. Il comando ln permette di fare riferimento al file collegato (linkato) con più di un nome e rappresenta un'alternativa di livello superiore all'uso degli alias (vedi Esempio 4-6).

ln crea semplicemente un riferimento, un puntatore al file, che occupa solo pochi byte.

Il comando ln è usato molto spesso con l'opzione -s, simbolico o "soft". Uno dei vantaggi dell'uso dell'opzione -s è che consente link alle directory o a file di filesystem diversi.

La sintassi del comando è un po' ingannevole. Per esempio: ln -s vecchiofile nuovofile collega nuovofile, creato con l'istruzione, all'esistente vecchiofile.

Attenzione

Nel caso sia già presente un file di nome nuovofile, viene visualizzato un messaggio d'errore.

Con i link si ha la possibilità di invocare uno stesso script (o qualsiasi altro eseguibile) con nomi differenti ottenendo un comportamento diverso in base al nome con cui è stato invocato.

Esempio 15-2. Ciao o arrivederci

#!/bin/bash
# hello.sh: Visualizzare "ciao" o "arrivederci"
#+          secondo le modalità di invocazione dello script.

# Eseguiamo un collegamento allo script nella directory di lavoro corrente($PWD):
#    ln -s hello.sh goodbye
# Ora proviamo ad invocare lo script in entrambi i modi:
# ./hello.sh
# ./goodbye


CHIAMATA_CIAO=65
CHIAMATA_ARRIVEDERCI=66

if [ $0 = "./goodbye" ]
then
  echo "Arrivederci!"
  # Se si desidera, qualche altro saluto dello stesso tipo.
  exit $CHIAMATA_ARRIVEDERCI
fi

echo "Ciao!"
# Qualche altro comando appropriato.
exit $CHIAMATA_CIAO
man, info

Questi comandi danno accesso alle informazioni e alle pagine di manuale dei comandi di sistema e delle utility installate. Quando sono disponibili, le pagine info, di solito, contengono una descrizione più dettagliata che non le pagine di manuale.

Note

[1]

Vengono chiamati dotfile quelli i cui nomi incominciano con un punto (dot), come ~/.Xdefaults, e che non vengono visualizzati con un semplice ls (sebbene ls -a ci riesca). Non possono neanche essere cancellati accidentalmente con un rm -rf *. I dotfile vengono solitamente usati come file di impostazione e configurazione nella directory home dell'utente.