Guida avanzata di scripting Bash: Un'approfondita esplorazione dell'arte dello scripting di shell | ||
---|---|---|
Indietro | Capitolo 15. Filtri, programmi e comandi esterni | Avanti |
È l'utility standard di archiviazione UNIX. [1] Dall'originale programma per il salvataggio su nastro (Tape ARchiving), si è trasformata in un pacchetto con funzionalità più generali che può gestire ogni genere di archiviazione con qualsiasi tipo di dispositivo di destinazione, dai dispositivi a nastro ai file regolari fino allo stdout (vedi Esempio 3-4). Tar GNU è stato implementato per accettare vari filtri di compressione, ad esempio tar czvf nome_archivio.tar.gz * che archivia ricorsivamente e comprime con gzip tutti i file, tranne quelli il cui nome inizia con un punto (dotfile), della directory di lavoro corrente ($PWD). [2]
Alcune utili opzioni di tar:
-c
crea
(un nuovo archivio)
-x
estrae (file da un
archivio esistente)
--delete
cancella (file da un
archivio esistente)
Questa opzione non funziona sui dispositivi a nastro magnetico. |
-r
accoda (file ad
un archivio esistente)
-A
accoda (file
tar ad un archivio esistente)
-t
elenca (il
contenuto di un archivio esistente)
-u
aggiorna
l'archivio
-d
confronta
l'archivio con un filesystem specificato
-z
usa
gzip sull'archivio
(lo comprime o lo decomprime in base all'abbinamento con
l'opzione -c
o -x
)
-j
comprime l'archivio
con bzip2
Poiché potrebbe essere difficile ripristinare dati da un archivio tar compresso con gzip è consigliabile, per l'archiviazione di file importanti, eseguire salvataggi (backup) multipli. |
Utility di archiviazione shell. I file di un archivio shell vengono concatenati senza compressione. Quello che risulta è essenzialmente uno script di shell, completo di intestazione #!/bin/sh e contenente tutti i necessari comandi di ripristino. Gli archivi shar fanno ancora la loro comparsa solo nei newsgroup Internet, dal momento che shar è stata sostituita molto bene da tar/gzip. Il comando unshar ripristina gli archivi shar.
Utility per la creazione e la manipolazione di archivi, usata principalmente per le librerie di file oggetto binari.
Il Red Hat Package Manager, o utility rpm, è un gestore per archivi binari o sorgenti. Tra gli altri, comprende comandi per l'installazione e la verifica dell'integrità dei pacchetti.
Un semplice rpm -i nome_pacchetto.rpm è di solito sufficiente per installare un pacchetto, sebbene siano disponibili molte più opzioni.
rpm -qf identifica il pacchetto che ha fornito un determinato file.
|
rpm -qa fornisce l'elenco completo dei pacchetti rpm installati su un sistema. rpm -qa nome_pacchetto elenca solo il pacchetto corrispondente a nome_pacchetto.
|
Comando specializzato per la copia di archivi (copy input and output), si incontra molto raramente, essendo stato soppiantato da tar/gzip. Le sue funzionalità, comunque, vengono ancora utilizzate, ad esempio per spostare una directory. Specificando (per la copia) un'appropriata dimensione del blocco (block size), diventa sensibilmente più veloce di tar.
Esempio 15-27. Utilizzo di cpio per spostare una directory
#!/bin/bash # Copiare una directory usando cpio. # Vantaggi dell'uso di 'cpio': # Velocità nella copia. Con le pipe è più veloce di 'tar'. # Adatto per la copia di file speciali (named pipe, ecc.) #+ dove 'cp' potrebbe fallire. ARG=2 E_ERR_ARG=65 if [ $# -ne "$ARG" ] then echo "Utilizzo: `basename $0` directory_origine directory_destinazione" exit $E_ERR_ARG fi origine=$1 destinazione=$2 find "$origine" -depth | cpio -admvp "$destinazione" # ^^^^^ ^^^^^ # Leggete le pagine di manuale di 'find' e 'cpio' per decifrare queste opzioni. # Esercizio: # --------- # Aggiungete del codice per verificare l'exit status ($?) della pipe #+ 'find | cpio' e che visualizzi degli appropriati messaggi d'errore nel caso #+ qualcosa non abbia funzionato correttamente. exit 0 |
Questo comando crea un archivio cpio da un archivio rpm.
Esempio 15-28. Decomprimere un archivio rpm
#!/bin/bash # de-rpm.sh: Decomprime un archivio 'rpm' : ${1?"Utilizzo: `basename $0` file_archivio"} # Bisogna specificare come argomento un archivio 'rpm'. TEMPFILE=$$.cpio # File temporaneo con nome "univoco". # $$ è l'ID di processo dello script. rpm2cpio < $1 > $TEMPFILE # Converte l'archivio rpm in #+ un archivio cpio. cpio --make-directories -F $TEMPFILE -i # Decomprime l'archivio cpio. rm -f $TEMPFILE # Cancella l'archivio cpio. exit 0 # Esercizio: # Aggiungete dei controlli per verificare se #+ 1) "file_archivio" esiste e #+ 2) è veramente un archivio rpm. # Suggerimento: verificate l'output del comando 'file'. |
Utility di compressione standard GNU/UNIX che ha sostituito la meno potente e proprietaria compress. Il corrispondente comando di decompressione è gunzip, equivalente a gzip -d.
L'opzione |
Il filtro zcat decomprime un file compresso con gzip allo stdout, come possibile input per una pipe o una redirezione. In effetti, è il comando cat che agisce sui file compressi (compresi quelli ottenuti con la vecchia utility compress). Il comando zcat equivale a gzip -dc.
Su alcuni sistemi commerciali UNIX, zcat è il sinonimo di uncompress -c, di conseguenza non funziona su file compressi con gzip. |
Vedi anche Esempio 7-7.
Utility di compressione alternativa, più efficiente (ma più lenta) di gzip, specialmente con file di ampie dimensioni. Il corrispondente comando di decompressione è bunzip2.
Le versioni più recenti di tar sono state aggiornate per supportare bzip2. |
È la vecchia utility proprietaria di compressione presente nelle distribuzioni commerciali UNIX. È stata ampiamente sostituita dalla più efficiente gzip . Le distribuzioni Linux includono, di solito, compress per ragioni di compatibilità, sebbene gunzip possa decomprimere i file trattati con compress.
Il comando znew trasforma i file dal formato compress al formato gzip. |
Altra utility di compressione. È un filtro che opera solo su elenchi di parole ASCII ordinate. Usa la sintassi standard dei filtri, sq < file-input > file-output. Veloce, ma non così efficiente come gzip. Il corrispondente filtro di decompressione è unsq, con la stessa sintassi di sq.
L'output di sq può essere collegato per mezzo di una pipe a gzip per una ulteriore compressione. |
Utility di archiviazione e compressione multipiattaforma, compatibile con il programma DOS pkzip.exe. Gli archivi "zippati" sembrano rappresentare, su Internet, il mezzo di scambio più comune rispetto ai "tarball".
Queste utility Linux consentono di decomprimere archivi compressi con i programmi DOS arc.exe, arj.exe e rar.exe.
Utility per identificare i tipi di file. Il comando file nome_file restituisce la specifica di nome_file, come ascii text o data. Fa riferimento ai magic number che si trovano in /usr/share/magic, /etc/magic o /usr/lib/magic, secondo le distribuzioni Linux/UNIX.
L'opzione -f
esegue
file in modalità
batch, per leggere
l'elenco dei file contenuto nel file indicato.
L'opzione -z
, se usata su un file compresso,
tenta di analizzare il tipo del file non compresso.
bash$ file test.tar.gz test.tar.gz: gzip compressed data, deflated, last modified: Sun Sep 16 13:34:51 2001, os: Unix bash file -z test.tar.gz test.tar.gz: GNU tar archive (gzip compressed data, deflated, last modified: Sun Sep 16 13:34:51 2001, os: Unix) |
# Ricerca gli script sh e Bash in una data directory: DIRECTORY=/usr/local/bin PAROLACHIAVE=Bourne # Script di shell Bourne e Bourne-Again file $DIRECTORY/* | fgrep $PAROLACHIAVE # Risultato: # /usr/local/bin/burn-cd: Bourne-Again shell script text executable # /usr/local/bin/burnit: Bourne-Again shell script text executable # /usr/local/bin/cassette.sh: Bourne shell script text executable # /usr/local/bin/copy-cd: Bourne-Again shell script text executable # . . . |
Esempio 15-29. Togliere i commenti da sorgenti C
#!/bin/bash # strip-comment.sh: Toglie i commenti (/* COMMENTO */) in un programma C. E_NOARG=0 E_ERR_ARG=66 E_TIPO_FILE_ERRATO=67 if [ $# -eq "$E_NOARG" ] then echo "Utilizzo: `basename $0` file-C" >&2 # Messaggio d'errore allo stderr. exit $E_ERR_ARG fi # Verifica il corretto tipo di file. tipo=`file $1 | awk '{ print $2, $3, $4, $5 }'` # "file $1" restituisce nome e tipo di file . . . # quindi awk rimuove il primo campo, il nome . . . # Dopo di che il risultato è posto nella variabile "tipo". tipo_corretto="ASCII C program text" if [ "$tipo" != "$tipo_corretto" ] then echo echo "Questo script funziona solo su file sorgenti C." echo exit $E_TIPO_FILE_ERRATO fi # Script sed piuttosto criptico: #-------- sed ' /^\/\*/d /.*\*\//d ' $1 #-------- # Facile da capire, se dedicate diverse ore ad imparare i fondamenti di sed. # È necessario aggiungere ancora una riga allo script sed per trattare #+ quei casi in cui una riga di codice è seguita da un commento. # Questo viene lasciato come esercizio (niente affatto banale). # Ancora, il codice precedente cancella anche le righe con un "*/" o "/*" #+ che non sono commenti, il che non è un risultato desiderabile. exit 0 # ---------------------------------------------------------------------------- # Il codice oltre la linea non viene eseguito a causa del precedente 'exit 0'. # Stephane Chazelas suggerisce la seguente alternativa: utilizzo() { echo "Utilizzo: `basename $0` file-C" >&2 exit 1 } STRANO=`echo -n -e '\377'` # oppure STRANO=$'\377' [[ $# -eq 1 ]] || utilizzo case `file "$1"` in *"C program text"*) sed -e "s%/\*%${STRANO}%g;s%\*/%${STRANO}%g" "$1" \ | tr '\377\n' '\n\377' \ | sed -ne 'p;n' \ | tr -d '\n' | tr '\377' '\n';; *) utilizzo;; esac # Questo può ancora essere ingannato da occorrenze come: # printf("/*"); # o # /* /* errato commento annidato */ # # Per poter gestire tutti i casi particolari (commenti in stringhe, commenti #+ in una stringa in cui è presente \", \\" ...) l'unico modo è scrivere un #+ parser C (usando, forse, lex o yacc?). exit 0 |
which comandoXXX restituisce il percorso assoluto di "comandoXXX". È utile per verificare se un particolare comando o utility è installato sul sistema.
$bash which rm
/usr/bin/rm |
Simile al precedente which, whereis comandoXXX restituisce il percorso assoluto di "comandoXXX" ed anche della sua pagina di manuale.
$bash whereis rm
rm: /bin/rm /usr/share/man/man1/rm.1.bz2 |
whatis filexxx ricerca "filexxx" nel database whatis. È utile per identificare i comandi di sistema e i file di configurazione. Può essere considerato una semplificazione del comando man.
$bash whatis whatis
whatis (1) - search the whatis database for complete words |
Esempio 15-30. Esplorare /usr/X11R6/bin
#!/bin/bash # Cosa sono tutti quei misteriosi eseguibili in /usr/X11R6/bin? DIRECTORY="/usr/X11R6/bin" # Provate anche "/bin", "/usr/bin", "/usr/local/bin", ecc. for file in $DIRECTORY/* do whatis `basename $file` # Visualizza le informazione sugli eseguibili. done exit 0 # Potreste desiderare di redirigere l'output di questo script, così: # ./what.sh >>whatis.db # o visualizzarne una pagina alla volta allo stdout, # ./what.sh | less |
Vedi anche Esempio 10-3.
Visualizza l'elenco dettagliato della directory. L'effetto è simile a ls -lb.
Questa è una delle fileutils GNU.
bash$ vdir total 10 -rw-r--r-- 1 bozo bozo 4034 Jul 18 22:04 data1.xrolo -rw-r--r-- 1 bozo bozo 4602 May 25 13:58 data1.xrolo.bak -rw-r--r-- 1 bozo bozo 877 Dec 17 2000 employment.xrolo bash ls -l total 10 -rw-r--r-- 1 bozo bozo 4034 Jul 18 22:04 data1.xrolo -rw-r--r-- 1 bozo bozo 4602 May 25 13:58 data1.xrolo.bak -rw-r--r-- 1 bozo bozo 877 Dec 17 2000 employment.xrolo |
Il comando locate esegue la ricerca dei file usando un database apposito. Il comando slocate è la versione di sicurezza di locate (che può essere l'alias di slocate).
$bash locate hickson
/usr/lib/xephem/catalogs/hickson.edb |
Rivela il file a cui punta un link simbolico.
bash$ readlink /usr/bin/awk ../../bin/gawk |
Il comando strings viene usato per cercare le stringhe visualizzabili in un file dati o in un file binario. Elenca le sequenze di caratteri trovate nel file di riferimento. E' utile per un esame rapido e sommario di un file core di scarico della memoria o per dare un'occhiata ad un file di immagine sconosciuto (strings file-immagine | more potrebbe restituire qualcosa come JFIF che indica un file grafico jpeg). In uno script, si può controllare l'output di strings con grep o sed. Vedi Esempio 10-7 e Esempio 10-9.
Esempio 15-31. Un comando strings "migliorato"
#!/bin/bash # wstrings.sh: "word-strings" (comando "strings" migliorato) # # Questo script filtra l'output di "strings" confrontandolo #+ con un file dizionario. # In questo modo viene eliminato efficacemente il superfluo, #+ restituendo solamente le parole riconosciute. # ==================================================================== # Verifica standard del/degli argomento/i dello script ARG=1 E_ERR_ARG=65 E_NOFILE=66 if [ $# -ne $ARG ] then echo "Utilizzo: `basename $0` nomefile" exit $E_ERR_ARG fi if [ ! -f "$1" ] # Verifica l'esistenza del file. then echo "Il file \"$1\" non esiste." exit $E_NOFILE fi # ==================================================================== LUNMINSTR=3 # Lunghezza minima della stringa. DIZIONARIO=/usr/share/dict/linux.words # File dizionario. # Può essere specificato un file #+ dizionario diverso purché #+ di una parola per riga. elenco=`strings "$nome_file" | tr A-Z a-z | tr '[:space:]' Z | \ tr -cs '[:alpha:]' Z | tr -s '\173-\377' Z | tr Z ' '` # Modifica l'output del comando 'strings' mediante diversi passaggi a 'tr'. # "tr A-Z a-z" trasforma le lettere maiuscole in minuscole. # "tr '[:space:]' Z" trasforma gli spazi in Z. # "tr -cs '[:alpha:]' Z" trasforma i caratteri non alfabetici in Z, #+ riducendo ad una sola le Z multiple consecutive. # "tr -s '\173-\377' Z" trasforma tutti i caratteri oltre la 'z' in Z, #+ riducendo ad una sola le Z multiple consecutive, liberandoci così di tutti i #+ caratteri strani che la precedente istruzione non è riuscita a trattare. # Infine, "tr Z ' '" trasforma tutte queste Z in spazi, che saranno #+ considerati separatori di parole dal ciclo che segue. # ********************************************************** # Notate la tecnica di concatenare diversi 'tr', #+ ma con argomenti e/o opzioni differenti ad ogni passaggio. # ********************************************************** for parola in $elenco # Importante: # non bisogna usare $elenco col quoting. # "$elenco" non funziona. # Perché no? do lunstr=${#parola} # Lunghezza della stringa. if [ "$lunstr" -lt "$LUNMINSTR" ] # Salta le stringhe con meno #+ di 3 caratteri. then continue fi grep -Fw $parola "$DIZIONARIO" # Cerca solo le parole complete. ^^^ # Opzioni "stringhe Fisse" e #+ "parole (words) intere". done exit $? |
diff: flessibile utility per il confronto di file. Confronta i file di riferimento riga per riga, sequenzialmente. In alcune applicazioni, come nei confronti di dizionari, è vantaggioso filtrare i file di riferimento con sort e uniq prima di collegarli tramite una pipe a diff. diff file-1 file-2 visualizza le righe dei file che differiscono, con le parentesi acute ad indicare a quale file ogni particolare riga appartiene.
L'opzione --side-by-side
di
diff visualizza riga per riga, in colonne
separate, ogni file confrontato con un segno indicante le
righe non coincidenti. Le opzioni -c
e
-u
, similmente, rendono più facile
l'interpretazione dell'output del comando.
Sono disponibili diversi front-end per diff, quali sdiff, wdiff, xdiff e mgdiff.
Il comando diff restituisce exit status 0 se i file confrontati sono identici, 1 in caso contrario. Questo consente di utilizzare diff per un costrutto di verifica in uno script di shell (vedi oltre). |
L'uso più comune di diff
è quello per creare file di differenze da
utilizzare con patch. L'opzione
-e
produce file idonei all'utilizzo con script
ed o ex.
patch: flessibile utility per gli aggiornamenti. Dato un file di differenze prodotto da diff, patch riesce ad aggiornare un pacchetto alla versione più recente. È molto più conveniente distribuire un file di "differenze", di dimensioni relativamente minori, che non l'intero pacchetto aggiornato. Il "patching" del kernel è diventato il metodo preferito per la distribuzione delle frequenti release del kernel Linux.
patch -p1 <file-patch # Prende tutte le modifiche elencate in 'file-patch' # e le applica ai file che sono specificati in "file-patch". # Questo esegue l'aggiornamento del pacchetto alla versione più recente. |
Patch del kernel:
cd /usr/src gzip -cd patchXX.gz | patch -p0 # Aggiornamento dei sorgenti del kernel usando 'patch'. # Dal file "README" della documentazione del kernel Linux, # di autore anonimo (Alan Cox?). |
Il comando diff riesce anche ad eseguire un confronto ricorsivo tra directory (sui file in esse contenuti).
|
Versione estesa di diff che confronta tre file alla volta. Questo comando restituisce, come exit status, 0 in caso di successo, ma sfortunatamente non fornisce alcuna informazione sui risultati del confronto.
bash$ diff3 file-1 file-2 file-3 ==== 1:1c Questa è la riga 1 di "file-1". 2:1c Questa è la riga 1 di "file-2". 3:1c Questa è la riga 1 di "file-3" |
Confronta e/o visualizza due file con lo scopo di unirli in un unico file. A causa della sua natura interattiva, è difficile che questo comando venga impiegato negli script.
Il comando cmp è la versione più semplice di diff. Mentre diff elenca le differenze tra i due file, cmp mostra semplicemente i punti in cui differiscono.
Come diff, cmp restituisce exit status 0 se i file confrontati sono identici, 1 in caso contrario. Questo ne consente l'impiego per un costrutto di verifica in uno script di shell. |
Esempio 15-32. Utilizzare cmp in uno script per confrontare due file
#!/bin/bash ARG=2 # Lo script si aspetta due argomenti. E_ERR_ARG=65 E_NONLEGGIBILE=66 if [ $# -ne "$ARG" ] then echo "Utilizzo: `basename $0` file1 file2" exit $E_ERR_ARG fi if [[ ! -r "$1" || ! -r "$2" ]] then echo "Entrambi i file, per essere confrontati, devono esistere" echo "ed avere i permessi di lettura." exit $E_NONLEGGIBILE fi cmp $1 $2 &> /dev/null # /dev/null elimina la visualizzazione del #+ risultato del comando"cmp". # cmp -s $1 $2 ottiene lo stesso risultato (opzione "-s" di "cmp") # Grazie Anders Gustavsson per averlo evidenziato. # # Funziona anche con 'diff', vale a dire, diff $1 $2 &> /dev/null if [ $? -eq 0 ] # Verifica l'exit status del comando "cmp". then echo "Il file \"$1\" è identico al file \"$2\"." else echo "Il file \"$1\" è diverso dal file \"$2\"." fi exit 0 |
Si usa zcmp per i file compressi con gzip. |
Versatile utility per il confronto di file. I file da confrontare devono essere ordinati.
comm -opzioni primo-file secondo-file
comm file-1 file-2 visualizza il risultato su tre colonne:
colonna 1 = righe uniche appartenenti a file-1
colonna 2 = righe uniche appartenenti a file-2
colonna 3 = righe comuni ad entrambi i file.
Alcune opzioni consentono la soppressione di una o più colonne di output.
-1
sopprime la colonna
1
-2
sopprime la colonna
2
-3
sopprime la colonna
3
-12
sopprime entrambe
le colonne
1 e 2, ecc.
È un comando utile per confrontare "dizionari" o elenchi di parole -- file di testo ordinati, con una parola per riga.
Elimina il percorso del file, visualizzando solamente il suo nome. Il costrutto basename $0 permette allo script di conoscere il proprio nome, vale a dire, il nome con cui è stato invocato. Si può usare per i messaggi di "utilizzo" se, per esempio, uno script viene eseguito senza argomenti:
echo "Utilizzo: `basename $0` arg1 arg2 ... argn" |
Elimina basename, dal nome del file, visualizzando solamente il suo percorso.
basename e dirname possono operare su una stringa qualsiasi. Non è necessario che l'argomento si riferisca ad un file esistente e neanche essere il nome di un file (vedi Esempio A-7). |
Esempio 15-33. basename e dirname
#!/bin/bash a=/home/bozo/daily-journal.txt echo "Basename di /home/bozo/daily-journal.txt = `basename $a`" echo "Dirname di /home/bozo/daily-journal.txt = `dirname $a`" echo echo "La mia cartella personale è `basename ~/`." # funziona anche `basename ~`. echo "La directory della mia cartella personale è `dirname ~/`." # funziona anche `dirname ~`. exit 0 |
Utility per suddividere un file in porzioni di dimensioni minori. Sono solitamente impiegate per suddividere file di grandi dimensioni allo scopo di eseguirne il salvataggio su floppy disk, per l'invio tramite e-mail o per effettuarne l'upload su un server.
Il comando csplit suddivide il file in base ad un dato criterio. La suddivisione viene eseguita nei punti in cui i modelli sono verificati.
Sono utility per creare le checksum. Una checksum è un numero ricavato con un calcolo matematico eseguito sul contenuto di un file, con lo scopo di verificarne l'integrità. Uno script potrebbe verificare un elenco di checksum a fini di sicurezza, per esempio per assicurarsi che il contenuto di indispensabili file di sistema non sia stato modificato o corrotto. Per applicazioni di sicurezza, si dovrebbe utilizzare il comando md5sum a 128-bit (message digest 5 checksum) o, ancor meglio, il nuovissimo sha1sum (Secure Hash Algorithm).
bash$ cksum /boot/vmlinuz 1670054224 804083 /boot/vmlinuz bash$ echo -n "Top Secret" | cksum 3391003827 10 bash$ md5sum /boot/vmlinuz 0f43eccea8f09e0a0b2b5cf1dcf333ba /boot/vmlinuz bash$ echo -n "Top Secret" | md5sum 8babc97a6f62a4649716f4df8d61728f - |
Il comando cksum visualizza anche la dimensione, in byte, del suo riferimento. sia esso un file o lo stdout. I comandi md5sum e sha1sum visualizzano un trattino quando l'input proviene dallo stdout. |
Esempio 15-34. Verificare l'integrità dei file
#!/bin/bash # file-integrity.sh: Verifica se i file di una data directory # sono stati modificati senza autorizzazione. E_DIR_ERRATA=70 E_ERR_DBFILE=71 dbfile=File_record.md5 # Nome del file che contiene le registrazioni (file database). crea_database () { echo ""$directory"" > "$dbfile" # Scrive il nome della directory come prima riga di dbfile. md5sum "$directory"/* >> "$dbfile" # Accoda le checksum md5 e i nomi dei file. } verifica_database () { local n=0 local nomefile local checksum # --------------------------------------------------------- # # Questa verifica potrebbe anche non essere necessaria, ma è #+ meglio essere pignoli che rischiare. if [ ! -r "$dbfile" ] then echo "Impossibile leggere il database delle checksum!" exit $E_ERR_DBFILE fi # --------------------------------------------------------- # while read record[n] do directory_verificata="${record[0]}" if [ "$directory_verificata" != "$directory" ] then echo "Le directory non corrispondono!" # E' stato indicato un nome di directory sbagliato. exit $E_DIR_ERRATA fi if [ "$n" -gt 0 ] # Non è il nome della directory. then nomefile[n]=$( echo ${record[$n]} | awk '{ print $2 }' ) # md5sum scrive nel primo campo la checksum, nel #+ secondo il nome del file. checksum[n]=$( md5sum "${nomefile[n]}" ) if [ "${record[n]}" = "${checksum[n]}" ] then echo "${nomefile[n]} non è stato modificato." elif [ "`basename ${nomefile[n]}`" != "$dbfile" ] # Salta il database delle checksum, #+ perché cambia ad ogni invocazione dello script. # --- # Questo significa, purtroppo, che quando si esegue #+ lo script su $PWD, la coincidenza con il #+ file database delle checksum non viene rilevata. # Esercizio: Risolvete questo problema. then echo "${nomefile[n]} : CHECKSUM ERRATA!" # Il file è stato modificato dall'ultima verifica. fi fi let "n+=1" done <"$dbfile" # Legge il database delle checksum. } # ============================================================= # # main () if [ -z "$1" ] then directory="$PWD" # Se non altrimenti specificata, usa la else #+ directory di lavoro corrente. directory="$1" fi clear # Pulisce lo schermo. echo " In esecuzione il controllo dell'integrità dei file in $directory" echo # ------------------------------------------------------------------- # if [ ! -r "$dbfile" ] # Occorre creare il database? then echo "Sto creando il database, \""$directory"/"$dbfile"\"."; echo crea_database fi # ------------------------------------------------------------------- # verifica_database # Esegue il lavoro di verifica. echo # Sarebbe desiderabile redirigere lo stdout dello script in un file, #+ specialmente se la directory da verificare contiene molti file. exit 0 # Per una verifica d'integrità molto più approfondita, #+ considerate l'impiego del pacchetto "Tripwire", #+ http://sourceforge.net/projects/tripwire/. |
Vedi anche Esempio A-19 e Esempio 33-14 per un uso creativo del comando md5sum.
Essendoci state delle notizie che segnalano che la codifica md5sum a 128 bit è stata spezzata, non si può che dare il benvenuto, tra gli strumenti per il calcolo della checksum, al più sicuro sha1sum a 160 bit. Alcuni consulenti per la sicurezza sono dell'opinione che anche sha1sum possa essere compromessa. Per cui, a quando la prossima utility a 512 bit?
|
Cancella in modo sicuro un file, sovrascrivendolo diverse volte con caratteri casuali prima di cancellarlo definitivamente. Questo comando ha lo stesso effetto di Esempio 15-55, ma esegue il compito in maniera più completa ed elegante.
Questa è una delle fileutils GNU.
Tecniche di indagine avanzate potrebbero essere ancora in grado di recuperare il contenuto di un file anche dopo l'uso di shred. |
Questa utility codifica i file binari (immagini, file musicali, file compressi, ecc.) in caratteri ASCII, rendendoli disponibili per la trasmissione nel corpo di un messaggio e-mail o in un post di newsgroup. È particolarmente utile nei casi in cui non è disponibile la codifica MIME (multimedia).
Inverte la codifica, ripristinando i file binari, codificati con uuencode, al loro stato originario.
Esempio 15-35. Decodificare file
#!/bin/bash # Decodifica con uudecode tutti i file della directory di lavoro corrente #+ cifrati con uuencode. righe=35 # 35 righe di intestazione (molto generoso). for File in * # Verifica tutti i file presenti in $PWD. do ricerca1=`head -n $righe $File | grep begin | wc -w` ricerca2=`tail -n $righe $File | grep end | wc -w` # Decodifica i file che hanno un "begin" nella parte iniziale e un "end" #+ in quella finale. if [ "$ricerca1" -gt 0 ] then if [ "$ricerca2" -gt 0 ] then echo "Decodifico con uudecode - $File -" uudecode $File fi fi done # Notate che se si invoca questo script su se stesso, l'esecuzione è ingannata #+ perché pensa di trovarsi in presenza di un file codificato con uuencode, #+ poiché contiene sia "begin" che "end". # Esercizio: # Modificate lo script per verificare in ogni file l'intestazione di un #+ newsgroup, saltando al file successivo nel caso non venga trovata. exit 0 |
Il comando fold -s può essere utile (possibilmente in una pipe) per elaborare messaggi di testo di grandi dimensioni, decodificati con uudecode, scaricati dai newsgroup Usenet. |
I comandi mimencode e mmencode elaborano gli allegati e-mail nei formati di codifica MIME. Sebbene i gestori di e-mail (mail user agents come pine o kmail) siano normalmente in grado di gestirli automaticamente, queste particolari utility consentono di manipolare tali allegati manualmente, da riga di comando o in modalità batch per mezzo di uno script di shell.
Una volta questa era l'utility standard UNIX per la cifratura di file. [3] Regolamenti governativi (USA N.d.T.), attuati per ragioni politiche, che proibiscono l'esportazione di software crittografico, hanno portato alla scomparsa di crypt da gran parte del mondo UNIX, nonché dalla maggioranza delle distribuzioni Linux. Per fortuna i programmatori hanno prodotto molte alternative decenti, tra le quali cruft realizzata proprio dall'autore del libro (vedi Esempio A-4).
Crea un file temporaneo [4] con nome "univoco". Invocata da riga di comando senza alcun argomento, crea un file vuoto (lunghezza zero) nella directory /tmp.
bash$ mktemp /tmp/tmp.zzsvql3154 |
PREFISSO=nomefile tempfile=`mktemp $PREFISSO.XXXXXX` # ^^^^^^ Occorrono almeno 6 posti per #+ il suffisso del nome del file. # Se non viene indicato nessun nome di file, #+ viene usato "tmp.XXXXXXXXXX" come nome di default. echo "nome del file temporaneo = $tempfile" # nome del file temporaneo = nomefile.QA2ZpY # o qualcosa del genere... # Crea un file con quel nome nella directory di lavoro corrente #+ con impostazione dei permessi a 600. # "umask 177" diventa, quindi, inutile, # sebbene il suo uso sia sempre una buona pratica di programmazione. |
Utility per costruire e compilare pacchetti binari. Può anche essere usata per una qualsiasi serie di operazioni che devono essere eseguite a seguito di successive modifiche nei file sorgenti.
Il comando make verifica Makefile, che è un elenco di dipendenze ed operazioni che devono essere svolte.
Comando speciale per la copia di file. È simile a cp, ma in grado di impostare i permessi e gli attributi dei file copiati. Questo comando sembra fatto su misura per l'installazione di pacchetti software e come tale appare frequentemente nei Makefile (nella sezione make install). Potrebbe essere usato allo stesso modo in script d'installazione.
Questa utility, scritta da Benjamin Lin e collaboratori, converte i file di testo in formato DOS (righe che terminano con CR-LF) nel formato UNIX (righe che terminano con il solo LF), e viceversa.
Il comando ptx [file-indicato] produce un indice permutato (elenco a riferimento incrociato) del file. Questo, se necessario, può essere successivamente filtrato e ordinato in una pipe.
Comandi per visualizzare un file, o un flusso, di testo allo stdout, una schermata alla volta. Possono essere usati per filtrare l'output dello stdout . . . o di uno script.
Un'applicazione interessante di more è la "verifica preventiva" di una sequenza di comandi, per prevenire conseguenze potenzialmente spiacevoli.
ls /home/bozo | awk '{print "rm -rf " $1}' | more # ^^^^ # Verifica l'effetto della seguente (disastrosa) riga di comando: # ls /home/bozo | awk '{print "rm -rf " $1}' | sh # Evita l'esecuzione da parte della shell . . .^^ |
[1] | Nel significato qui inteso, un archivio è semplicemente una serie di file correlati registrati in una singola locazione. |
[2] | tar czvf nome_archivio.tar.gz * include i dotfile presenti nelle directory che si trovano al di sotto della directory di lavoro corrente. Questa è una "funzionalità" non documentata del tar GNU. |
[3] | Cifratura di tipo simmetrico, usata per i file su un sistema singolo o su una rete locale, contrapposta a quella a "chiave pubblica", di cui pgp è il ben noto esempio. |
[4] | Crea una directory temporanea
se richiamato con l'opzione |