Shell - DISCo

Transcript

Shell - DISCo
Shell - Scripting Programming
1
Che cos’è la shell di Linux?
La shell è un interprete di comandi. Essa esegue i comandi letti da standard input
oppure da file.
La shell non fa parte del kernel del sistema operativo, ma usa il kernel per eseguire
i comandi.
2
Quale shell?
Diverse shell sono disponibili sotto Linux. Le più comuni sono:
• BASH (Bourne-Again SHell): è freeware ed è molto comune.
• CSH (C SHell): la sua sintassi ed il suo uso sono molto simili al linguaggio C.
• KSH (Korn SHell).
• TCSH: una versione più avanzata della CSH.
3
Quale shell?
Per trovare tutte le shell che sono disponibili sul proprio sistema, si può usare il
seguente comando:
$ cat /etc/shells
Ogni shell ha una diversa sintassi e mette a disposizione un diverso insieme di funzionalità predefinite.
In MS-DOS, il nome della shell è COMMAND.COM. Essa è stata concepita per gli
stessi scopi, ma è molto meno potente delle shell di Linux.
Per sapere quale shell si sta usando, occorre digitare il seguente comando:
echo $SHELL
4
Che cos’è uno script di Shell?
La definizione più semplice di script di shell è:
“ Una serie di comandi di shell scritti in un file di testo “
Successivamente sono stati introdotti alcuni costrutti di controllo tipici di un vero
linguaggio di programmazione, al fine di rendere gli script di shell più potenti.
5
Perché usare gli script di Shell?
• Permettono di creare nuovi comandi personalizzati.
• Permettono di risparmiare tempo (esecuzione di un solo comando, invece di
molti comandi in sequenza).
• Permettono di automatizzare dei task che devono essere eseguiti con alta frequenza (ad esempio tutti i giorni alla stessa ora).
• Permettono di facilitare il ruolo dell’Amministratore di Sistema.
6
Informazioni varie
Gli esempi che verranno mostrati in questo corso sono stati eseguiti usando la bash
shell ed usando Linux Red Hat versione 6.x+.
7
Getting Started with Shell Programming
8
Come scrivere uno script di shell
Per eseguire uno script di shell, i passi sono i seguenti:
• Scrivere lo script utilizzando un editore di testi (vi, emacs, xemacs, mcedit, kedit, etc.)
• Dopo aver scritto e salvato il file di testo che contiene lo script, settare i permessi di
esecuzione per il vostro utente. Il comando da usare è chmod e la sintassi è:
$ chmod +x nome-del-file
$ chmod 755 nome-del-file (scrittura e lettura ed esecuzione per owner, solo lettura ed
esecuzione per gruppo e altri)
$ chmod 777 nome-del-file (scrittura, lettura ed esecuzione per tutti)
...
• Eseguire lo script con la seguente sintassi:
$ ./nome-del-file
$ bash nome-del-file
$ sh nome-del-file
9
Il primo script di shell
Aprire un editore di testo e scrivere:
clear
echo “Hello World!”
Salvare il file col nome s1.sh.
(nota: dare l’estensione .sh agli script di shell è una convenzione, ma non un’obbligo:
nessuna estensione è espressamente richiesta).
Eseguire:
$ chmod 755 s1.sh
$ ./s1.sh
Viene ripulito il terminale, viene scritto Hello World! e, nella riga successiva viene
restituito il prompt in modo che l’utente possa digitare il prossimo comando.
10
Commenti
Tutte le righe che cominciano con il simbolo “#” sono considerati commenti. Ad
esempio, il file s1.sh può essere modificato nel modo seguente:
#
# Questo e’ il mio primo
# script di shell
#
clear
echo “Hello World!”
11
Il secondo script di shell
Aprire un file con un editore di testo, chiamarlo s2.sh e scrivere:
clear
echo "hello $USER"
echo "today is: "; date
echo "number of user login: "; who | wc -l
echo "Calendar: "; cal
exit 0
12
Variabili
In Linux esistono due tipi di variabile:
• Variabili di sistema: create e gestite dal sistema Linux stesso. Questo tipo di
variabile viene normalmente chiamata con CARATTERI MAIUSCOLI.
• Variabili definite dall’utente (User Defined Variables, UDV): create e gestite
dall’utente. Normalmente si indicano con caratteri minuscoli.
13
Variabili
Alcune delle variabili di sistema più importanti sono:
• BASH, che contiene il path dell’eseguibile della bash shell.
• BASH VERSION: la versione della bash shell in uso.
• COLUMNS: il numero di colonne dello schermo.
• HOME: il path della propria home directory.
• LINES: il numero di linee dello schermo.
• OSTYPE: il tipo del sistema operativo in uso.
14
• PATH: tutti i path che contengono eseguibili.
• PS1: i settaggi che permettono di creare la forma del prompt.
• PWD: la directory corrente
• SHELL: la shell correntemente in uso con il suo path.
• USERNAME: nome dell’utente correntemente loggato sul PC.
Per vedere il valore di ognuna di queste variabili usare il comando echo. Ad esempio:
$ echo $USERNAME
Se ci si dimentica il dollaro dopo USERNAME, stampa la stringa USERNAME. Il dollaro
consente di stamparne il valore.
15
User Defined Variables
Per definire una variabile utente, la sintassi è:
variable-name=value
Esempio
$ no=10 va bene.
$ 10=no NON va bene: i valori devono essere a destra dell’uguale. 10 non è un
nome di variabile corretto, perché comincia con una cifra.
$ vech=Bus è corretto e definisce una variabile di nome vech il cui valore è Bus.
Anche per visualizzare il valore di una USV si può esare il comando echo esattamente
come nel caso delle variabili di sistema.
16
Nomi di variabili (regole valide sia per variabili di sistema
che per UDV)
• Deve cominciare con carattere alfanumerico.
• Non deve contenere spazi vuoti. Inoltre, quando si definisce una variabile assegnandole un valore, occorre non mettere gli spazi neanche prima e dopo il
simbolo “=”:
$
$
$
$
no=10 va bene
no =10 NON va bene
no= 10 NON va bene
no = 10 NON va bene
• Le variabili sono “case sensitive”, quindi no è diversa da No.
17
• Si possono definire variabili NULL, ovvero variabili che non hanno alcun valore
al momento della loro definizione, come segue:
$ vech=
$ vech=“ ”
• I caratteri ?, * ed altri sono vietati.
18
Ancora sulle variabili
Tutte le variabili usate normalmente sono variabili locali.
Una variabile locale può essere usata in una shell, ma se si apre un’altra shell, esse
non sono più visibili.
Esempio
$ veicolo=Bus
$ echo $veicolo
Bus
$ /bin/bash
$ echo $veicolo
<non scrive niente>
$ veicolo=Car
$ echo $veicolo
Car
$ exit
$ echo $veicolo
Bus
19
Variabili globali
Per avere variabili di shell globali, (ovvero variabili che nonostante siano state definite
in una “vecchia” shell sono accessibile anche dalle “nuove” shells), occorre usare il
comando export.
Sintassi:
export var1 var2 ...
varN
Esempio
$ veicolo = Bus
$ echo $veicolo
Bus
$ export veicolo
$ /bin/bash
$ echo $veicolo
Bus
$ exit
$ echo $veicolo
Bus
20
Aritmetica di shell
Si possono scrivere cose del tipo:
$ expr op1 operatore op2
e verrà stampato il risultato dell’espressione a sinistra della parola chiave expr.
Esempi
$ expr 1 + 3 se si digita return (invio), il sistema risponde 4.
Altri esempi:
expr 2 - 1
expr 10 / 2
expr 20 % 3
expr 10 /∗ 3 (dato che il simbolo ∗ è un simbolo speciale)
21
Ancora aritmetica di shell
Si può anche scrivere:
$ echo ‘expr 6 + 3‘
e l’effetto è lo stesso (viene stampato 9).
Si noti che:
• Prima della parola chiave expr e dopo l’espressione si è usato il simbolo ‘ (back
quote) e non il simbolo ’ (quote).
• Quote, oppure double quote (“), non avrebbero funzionato.
22
Considerazioni sulle virgolette
• Double quote (“): tutti i caratteri compresi tra double quotes (eccetto / e $)
perdono il loro significato (diventano caratteri facenti parte di una costante di
tipo stringa).
• Single quote (’): tutto ciò che è interno a single quotes rimane immutato.
• Back quote (‘): ciò che è compreso all’interno delle back quotes viene interpretato come un comando da eseguire.
23
Exit Status
In conseguenza dell’esecuzione di un comando, Linux, per default, può restituire due
valori, a secondo che il comando sia andato a buon fine o meno:
• zero: il comando ha avuto successo (terminazione senza errori).
• diverso da zero: terminazione con errore.
Come si fa a sapere se un comando è terminato con un errore o meno?
Linux mette a disposizione una particolare variabile di shell: $?
24
Esempio
Supponiamo che un file di nome fileNonEsistente non sia presente sull’hard disk.
Se viene digitato il comando:
$ rm fileNonEsistente
verrà visualizzato un messaggio di errore del tipo:
rm: cannot remove ‘fileNonEsistente‘: No such file or directory
A questo punto, se viene digitato il comando:
$ echo $?
viene visualizzato un numero diverso da zero per indicare che c’è stato un errore.
Se invece si digita:
$ ls
$ $?
verrà stampato 0 ad indicare che il comando ha avuto successo.
25
Il comando read
Viene usato per ottenere un input da tastiera. La sua sintassi è:
read var1 var2 ...
varN
Ad esempio, il seguente script chiede all’utente di digitare un nome e aspetta che
l’utente scriva una stringa e poi digiti ENTER (INVIO). A questo punto, ciò che
l’utente ha scritto viene memorizzato nella variabile fname e successivamente stampato a video:
echo ’’Your first name please: ’’
read fname
echo ‘‘Hello $fname !’’
26
Wild Cards
• ∗: matcha qualsiasi stringa o gruppo di caratteri.
Esempi:
$ ls ∗ visualizza tutti i file nella directory corrente.
$ ls ∗a visualizza tutti i file nella directory corrente il cui nome finisce per a.
$ ls ut∗.c visualizza tutti i file nella directory corrente il cui nome comincia per ut e che
hanno una estensione .c.
• ?: matcha un qualsiasi carattere singolo.
Esempi:
$ ls ? visualizza tutti i file nella directory corrente il cui nome è composto da un solo
carattere.
$ ls fo? visualizza tutti i file nella directory corrente il cui nome è composto da tre
caratteri di cui i primi due sono f ed o.
27
• [...]: matcha uno qualsiasi tra i caratteri inclusi.
Esempio:
$ ls [abc]* visualizza tutti i file nella directory corrente il cui nome comincia con a, con
b, oppure con c.
Nota: una coppia di caratteri separati da un simbolo - denota un range:
$ ls /bin/[a-c]* visualizza tutti i file nella directory bin il cui nome comincia per a, b o c
Analogamente, i simboli ! e “cappuccio” servono per negare:
$ ls /bin/[!a-o]
$ ls /bin/[^a-o]
visualizzano tutti i file nella directory bin che NON cominciano con una lettera compresa tra a
ed o.
28
Punto e virgola
È possibile mettere più comandi su una linea di comando, separandoli con ;
$ date; who prima stampa la data e poi gli utenti loggati.
$ date who restituisce un errore perché interpreta who come un parametro del
comando date.
Se ci sono più stringhe sulla command line senza alcun separatore, Linux interpreta
la prima come il comando da eseguire e le altre come i suoi parametri.
29
Parametri di uno script
Supponiamo di eseguire:
$ myshell foo bar
dove myshell è il nome di un file contenente uno script di shell.
All’interno dello script, $0 indicherà myshell, $1 indicherà foo (primo parametro),
$2 indicherà bar (secondo parametro). (NON si possono assegnare nuovi valori a
$1, $2, ...).
Esiste una variabile predefinita # il cui valore è il numero di parametri dello script in
esecuzione. Ad esempio, nel caso precedente, $# restituisce 2.
Al momento, uno script può avere al massimo 9 parametri.
30
Redirezione di input ed output
La maggior parte dei comandi visualizzano i risultati sullo standard output (schermo)
e prendono input dello standard input (tastiera).
Linux consente anche di usare dei files per l’input e l’output.
• $ ls > filename l’output di ls viene messo nel file filename. Se il file
esisteva già, viene sovrascritto.
• ls >> filename l’output di ls viene concatenato in fondo al file filename,
se esso esiste, altrimenti esso viene creato e il comando equivale a quello del
punto precedente.
• cat < myfiles interpreta il contenuto di myfiles come una lista di nomi
di files e ne visualizza il contenuto.
31
Esempi
Se digitiamo:
$ cat > sname
Linux si ferma ed aspetta che l’utente digiti il contenuto del nuovo file che si chiamerà
sname. Immaginiamo di digitare:
martina
alessia
francesca
eleonora
Se si digita CONTROL-D, si salva il file sname con questo contenuto.
32
A questo punto, si può digitare il comando:
$ sort < sname > sorted names
alla fine sorted names contiene i nomi in ordine alfabetico.
Altro esempio:
$ tr ”[a-z]” ”[A-Z]” < sname > cap names
trasforma tutti i nomi in lettere maiuscole e salva il nuovo file con il nome cap names.
Alla fine il file cap names contiene:
MARTINA
ALESSIA
FRANCESCA
ELEONORA
33
Pipe
Il pipe è una tecnica per connettere l’output di un programma con l’input di un altro
senza utilizzare file temporanei.
La sintassi è:
comando1 | comando2
Esempi:
$ ls | more l’output del comando ls è dato in input al comando more, in modo
tale che esso sia stampato una pagina di terminale alla volta.
$ who | sort l’output di who viene dato in input a sort: questo comando
stampa la lista di utenti correntemente loggati ordinata alfabeticamente.
34
Pipe
$ who | sort > user list
user list.
come sopra, ma l’output viene messo in un file
$ who | wc -l stampa il numero di caratteri“a capo”nella lista di utenti, ovvero
stampa il numero di utenti.
$ ls -l | wc -l analogamente, stampa il numero di files che sono presenti nella
directory corrente.
$ who | grep root stampa tutte le linee dell’output di who nelle quali compare
la parola root. Il comando grep stampa le linee che matchano un pattern.
35
Filtri
Un filtro è un comando Linux che riceve un input, esegue alcune azioni su esso e
restituisce un output.
Ad esempio, supponiamo di avere un file che si chiama hotel.txt, contenente 100
linee di dati. Da hotel.txt supponiamo di voler stampare i contenuti delle linee
da 20 a 30 e memorizzare il risultato in un file chiamati hlist. Il comando per fare
ciò è:
$ tail +20 < hotel.txt | head -n30 > hlist
Qui il comando head è un filtro che prende il suo input dal comando tail (il
comando tail comincia a selezionare dalla linea 20 del file hotel.txt), mentre il
suo output è rediretto sul file hlist.
36
Filtri
Un altro esempio:
$ sort < sname | uniq > u name
Qui uniq è un filtro che prende in input il risultato del comando sort, mentre il
suo output è rediretto nel file u name.
37
Condizioni
In script programming, il tipo booleano (che viene usato, ad esempio, per testare le
condizioni!) viene rappresentato come segue:
• Vero: 0
• Falso: Un qualsiasi valore diverso da zero.
Tipico esempio di uso: la terminazione. Se il valore restituito è zero, significa che
la terminazione è stata senza errori, se è diverso da zero, significa che c’è stato un
errore ed il numero mi dice che tipo di errore.
38
Costrutti per il controllo del flusso
39
Comando condizionale if-then
Sintassi:
if condizione
then
comando
fi
Una condizione può essere:
• Una espressione booleana (derivante, ad esempio, da confronto tra due valori).
• Una condizione di terminazione di un comando o di un altro script.
40
Esempio
Si apra un file di testo di nome showfile e vi si scriva dentro:
if cat $1
then
echo -e ‘‘\n\nFile $1 trovato e visualizzato con successo’’
fi
Si esegua:
$ chmod 755 showfile
$ ./showfile foo
Il nome dello script di shell è showfile ($0) e foo è il suo argomento ($1).
41
Descrizione del precedente esempio
Se esiste un file che si chiama foo nella directory dove viene eseguito lo script,
allora il comando cat lo visualizza sullo schermo e termina con successo (termina
restituendo il valore zero). In questo caso, il valore della condizione che viene testata
tramite il comando if è vero, e quindi il comando echo -e “...” viene eseguito.
Al contrario, se il file non viene trovato, allora il comando cat non termina con
successo (ovvero restituisce un valore diverso da zero) e quindi il comando echo -e
“...” non viene eseguito e si passa direttamente all’esecuzione del comando successivo.
42
Esempio
Si inserisca il seguente script in un file di nome rmif:
if rm $1
then
echo ‘‘File $1 cancellato!’’
fi
Si esegua:
$ chmod 775 rmif
Si esegua:
$ ./rmif foo
Qual’è il comportamento di questo script?
43
Espressioni
Fin’ora abbiamo usato il comando if per testare la condizione di terminazione di un
comando.
Si può anche usare per testare il valore di una espressione.
Una espressione nel linguaggio di scripting si può scrivere:
• Facendola precedere dalla parola chiave test
• Includendola tra parentesi graffe ([]).
44
Esempio
Script che controlla se un dato argomento è un numero positivo.
Si inserisca il seguente script in un file chiamato ispositive.
if test $1 -gt 0
# oppure [$1 -gt 0]
then
echo ‘‘$1 è un numero positivo’’
fi
Esecuzione:
$ chmod 755 ispositive
$ ./ispositive 5
5 è un numero positivo
$ ./is positive -45
$
<non viene scritto nulla!>
$ ./ispositive
test: -gt unary operator expected
45
Operatori
Operatori matematici:
-eq : uguale a
-ne : diverso da
-lt : minore di
- le : minore o uguale a
- gt : maggiore di
-ge : maggiore o uguale a
Operatori su stringhe:
string1 = string2 : uguaglianza
string1 != string2 : diversità
string1 : testa se string1 non è nulla, oppure non è definita
-n string1 : testa se string1 non è nulla ed esiste
-z string1 : testa se string1 è nulla ed esiste
46
Operatori
Operatori su file:
-s file : testa se file non è vuoto
-f file : testa se file esiste e non è una directory
-d dir : testa se dir esiste ed è una directory
-w file : testa se file è scrivibile
-r file : testa se file è read-only
-x file : testa se file è eseguibile
Operatori logici:
!expr : NOT
expr1 -a expr2 : AND
expr1 -o expr2 : OR
47
Comando condizionale if-then-else
Sintassi:
if condizione
then
comando1
else
comando2
fi
48
Esempio
Aprire un file di testo di nome isnump ed inserire il seguente codice:
if [$# -eq 0]
then
echo ‘‘$0: Devi digitare un numero intero!’’
exit 1
fi
if test $1 -gt 0
then
echo ‘‘$1 è un numero positivo’’
else
echo ‘‘$1 è un numero negativo’’
fi
49
Spiegazione
La prima parte dello script controlla se l’utente fornisce o meno un parametro dalla
riga di comando. Se non viene fornito nessun parametro, viene stampato un messaggio d’errore. Il comando if, infatti, controlla se il numero di argomenti ($#)
passato allo script è uguale (-eq) a zero. Se un qualunque numero di argomenti
viene passato allo script, la condizione è falsa e quindi il primo if non ha alcun
effetto.
50
Compilare ed eseguire come segue:
$ chmod 777 isnump
$ ./isnump 5
5 è un numero positivo
$ ./isnump -45
-45 è un numero negativo
$ ./isnump
./isnump:
devi digitare un numero intero!
$ ./isnump 0
0 è un numero negativo
Per evitare ciò, si può scrivere la condizione come: if test $1 -ge 0.
51
Esempio
Si inserisca nel file nestedif.sh il seguente script contenente un if-then-else
annidato:
sistemaOp=0
echo ‘‘1. Unix (Sun OS)’’
echo ‘‘2. Linux (Red Hat)’’
echo -n ‘‘Seleziona il tuo sistema operativo (1 o 2)’’
read sistemaOp
if [$sistemaOp -eq 1]
then
echo ‘‘Hai scelto Unix (Sun OS)’’
else
if [$sistemaOp -eq 2]
then
echo ‘‘Hai scelto Linux (Red Hat)’’
else
echo ‘‘Che cosa? Non ti piace Linux/Unix?!’’
fi
fi
52
if-then-else multilivello
Sistassi:
if condizione_1
then
comando_1
elif condizione_2
then
comando_2
elif condizione_3
then
comando_3
...
elif condizione_n
then
comando_n
else
comando_n+1
fi
53
Esempio
Sia elf il nome del file contenente il seguente script:
if [$1 -gt 0] ; then
echo ‘‘$1 è un numero positivo’’
elif [$1 -lt 0]
then
echo ‘‘$1 è un numero negativo’’
elif [$1 -eq 0]
then
echo ‘‘$1 è uguale a zero’’
else
echo ‘‘Opps! $1 non è un numero!’’
fi
Eseguire:
$ chmod 755 elf
$ ./elf 1
$ ./elf -2
$ ./elf 0
$ ./elf a
54
Loops
La bash supporta due tipi di loop:
• for
• while
Istruzioni per costruire un buon loop (valide per qualsiasi linguaggio di programmazione!):
• Inizializzare la (o le) variabile (i) usata nella condizione del loop, prima dell’esecuzione
del loop.
• Ricordarsi che il test della condizione viene eseguito all’inizio di ogni iterazione.
• Il “corpo” del loop deve terminare con un comando che modifica il valore della
(e) variabile (i) della condizione.
55
Ciclo for. Tipo 1
Sintassi
for <nome di variabile> in <lista>
do
comando
done
Esempio (in un file di nome testfor):
for i in 1 2 3 4 5
do
echo ‘‘Ciao $i volte’’
done
56
Esecuzione:
$ chmod +x testfor
$ ./testfor
Ciao 1 volte
Ciao 2 volte
Ciao 3 volte
Ciao 4 volte
Ciao 5 volte
57
Esempio
In un file di nome mtable:
if [$#
then
echo
echo
echo
echo
exit
fi
-eq 0]
‘‘Errore.’’
‘‘Sintassi corretta: $0 numero’’
‘‘Questo programma stampa la tavola pitagorica’’
‘‘del numero fornito in ingresso’’
1
n = $1
for i in 1 2 3 4 5 6 7 8 9 10
do
echo ‘‘$n * $i = ’expr $i \* $n’ ’’
done
58
Esecuzione:
$ chmod 755 mtable
$ ./mtable 7
7 * 1 = 7
7 * 2 = 14
...
7 * 10 = 70
$ ./mtable
Errore
Sintassi corretta:
./mtable numero
Questo programma stampa la tavola pitagorica
del numero fornito in ingresso
59
Ciclo for. Tipo 2
Sintassi
for ((comando1; expr; comando2))
do
comando3
done
Significato:
• Prima della prima iterazione viene eseguito comando1 (questo comando viene
normalmente usato per inizializzare le variabili che controllano il loop).
• Viene eseguita la sequenza comando3 ; comando2 finché expr rimane vera
(comando2 viene normalmente usato per modificare il valore delle variabili che
controllano il loop, in modo da assicurare le terminazione).
60
Esempio
In un file di nome esempioFor:
for (( i = 0; i <= 5; i++ ))
do
echo ‘‘Ciao $i volte’’
done
Esecuzione:
$ chmod +x esempioFor
$ ./esempioFor
Ciao 1 volte
Ciao 2 volte
Ciao 3 volte
Ciao 4 volte
Ciao 5 volte
61
Esempio
In un file chiamato nestedFor.sh:
for ((i = 1; i <= 5; i++))
do
for (( j = 1; j <= 5; j++ ))
do
echo -n ‘‘$i ’’
done
echo ‘‘’’
# Per stampare una linea bianca
done
Esecuzione:
$
$
1
2
3
4
5
chmod +x nestedFor.sh
./nestedFor.sh
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4
5 5 5 5
62
Esempio. Stampa di una scacchiera sullo schermo
In un file chiamato chessboard:
for (( i = 1; i <= 9; i++ ))
do
for ((j = 1; j <= 9; j++ ))
do
tot = ’expr $i + $j’
tmp = ’expr $tot % 2’
if [$tmp -eq 0]
then
echo -e -n ‘‘\033[47m
else
echo -e -n ‘‘\033[40m
fi
done
echo -e -n ‘‘\033[40m’’
#
echo ‘‘’’
#
done
’’
’’
per settare il background nero
per andare a nuova riga
63
Output:
64
Spiegazione
• I cicli sono ripetuti 9 volte perché le scacchiere sono grandi 9 × 9 caselle. Ogni
iterazione del ciclo più interno stampa una casella (o bianca o nera); ogni
iterazione del ciclo più esterno stampa una riga della scacchiera.
• La variabile tmp vale 0 se tot è pari e 1 se tot è dispari. Quindi la variabile tmp
viene usata per sapere se deve essere stampata una casella nera o una casella
bianca.
• Il comando
echo -e -n ‘‘\033[47m
stampa una casella bianca (il comando -e, che sta per “enable”, permette di
leggere e interpretare i caratteri che cominciano con backslash, normalmente
usati per i colori).
65
• Il comando
echo -e -n ‘‘\033[40m
stampa una casella nera.
• Utilità del comando:
echo -e -n ‘‘\033[40m
alla fine del corpo del ciclo più esterno: quando si è scelto un colore, esso viene
mantenuto per qualsiasi attività (compresa quella di stampare una linea vuota!).
Quindi, una volta settata l’ultima casella al colore bianco, i comandi successivi
permetterebbero di stampare una riga vuota, ma essa sarebbe bianca! Inoltre,
tutto lo sfondo della shell diventerebbe bianco! (provare a commentare questa
riga e vedere che succede).
• Il comando echo“ ” stampa una riga vuota.
66
Ciclo while
Sintassi:
while [condizione]
do
comando
done
67
Esempio
In un file chiamato ciclo:
if [$# -eq 0]
then
echo ‘‘Errore: occorre fornire un parametro numerico’’
echo ‘‘Stampa la tavola pitagorica di quel numero’’
exit 1
fi
n=$1
i=1
while [$i -le 10]
do
echo ‘‘$n * $i = ’expr $i \* $n’ ’’
i = ’expr $i + i’
done
Esecuzione:
$ chmod 755 ciclo
$ ./ciclo 7
68
Comando case
Quando il test è sul valore di un’unica variable, il comando case è una valida
alternativa all’if-then-else multilivello, in quanto risulta più leggibile.
Sintassi:
case $nome_di_variabile in
pattern_1) command_1;;
pattern_2) command_2;;
...
pattern_N) command_N;;
*)
command_N+1;;
esac
69
Il valore di nome di variabile viene confrontato con i valori pattern 1, pattern 2,
... fino a che non viene trovato un match (uno di questi valori è uguale al valore
della variabile). A quel punto, la shell esegue il comando relativo fino al simbolo
“;;”.
Il comando di default (comando N+1) viene eseguito se non viene trovato nessun
match.
70
Esempio
In file chiamato car:
if [-z $1]
# Se il parametro è nullo
then
rental=’’*** Unknown vehicle ***’’;
else
rental=$1
fi
case $rental in
‘‘car’’) echo ‘‘il veicolo è un’automobile’’
‘‘van’’) echo ‘‘il veicolo è un caravan’’
‘‘jeep’’) echo ‘‘il veicolo è una jeep’’
‘‘bike’’) echo ‘‘il veicolo è una bicicletta’’
*) echo ‘‘Mi dispiace, non conosco questo veicolo...’’
esac
71
Eseguire:
$ chmod +x car
$ ./car van
il veicolo è un caravan
$ ./car car
il veicolo è un’auto
$ ./car mercedes
Mi dispiace, non conosco questo veicolo...
72
Come debuggare uno script di shell
Esistono due opzioni che permettono di debuggare uno script di shell:
• -v: stampa le linee dello script mentre le esegue
• -x: ogni comando viene “espanso” e vengono visualizzati i valori delle variabili
ed i vari passaggi.
La sintassi per usare queste opzioni è:
sh opzione <nome dello script>
oppure
bash opzione <nome dello script>
73
Esempio
In un file chiamato somma.sh:
tot=’expr $1 + $2’
echo $tot
Esecuzione:
$ chmod 755 somma.sh
$ ./somma 4 5
9
$ sh -x somma 4 5
tot=’expr $1 + $2’
expr $1 + $2
++ expr 4 +5
+ tot = 9
echo $tot
+ echo 9
9
Dato che -x scrive molte cose, quando lo script è complicato conviene usare -v !!
74
Esecuzione condizionale (&& e ||)
&& e || sono operatori di controllo.
&& può essere interpretato come un AND logico.
|| può essere interpretato come un OR.
Funzionamento:
comando1
&&
comando2
comando2 è eseguito se e solo se comando1 restituisce un exit status uguale a zero.
(ovvero termina senza errori)
comando1
||
comando2
comando2 è eseguito se e solo se comando1 restituisce un exit status diverso da zero.
(ovvero termina con un errore)
75
Gli operatori && e || possono essere usati insieme:
comando1
&&
comando2
||
comando3
Se comando1 restituisce un exit status uguale a zero (ovvero termina senza errori),
allora viene eseguito comando2, altrimenti viene eseguito comando3.
Esempio
$ rm myf && echo ‘‘File myf cancellato con successo’’ || echo ‘‘File myf non trovato’
76
Funzioni
77
Funzioni
Sintassi:
nome-funzione()
{
comando
return
}
Il comando return termina la funzione ed è obbligatorio.
78
Esempio
Sulla linea del prompt digitare:
$ SayHello()
{
echo ‘‘Ciao $LOGNAME’’
return
}
Al momento in cui viene chiusa la parentesi graffa, viene restituito di nuovo il prompt per eseguire
il prossimo comando. Per eseguire la funzione, sempre dalla linea del prompt, digitare:
$ SayHello
Ciao lvannesc
79
Nota: una volta che si spegne il computer e lo si riaccende, la funzione SayHello
verrà perduta: essa viene creata solo per la sessione corrente.
Se vogliamo che la funzione non venga perduta al momento della terminazione della
sessione di lavoro, possiamo aggiungere la funzione al file /etc/bashrc. Ciò può
essere fatto solo tramite la password di root.
In questo modo la funzione sarà visibile a tutti gli utenti.
Alternativamente, la funzione può essere messa nel file .bashrc che si trova nella
home directory di un particolare utente, ed allora sarà utilizzabile solo da parte di
quell’utente.
Una volta fatto questo, per eseguire la funzione occorre uscire e rientrare, oppure, supponendo
di essere nella directory che contiene il file .bashrc, digitare:
$ source .bashrc
(se non siamo nella directory che contiene il file .bashrc, occorre digitare il path completo)
80
Nota
Se vogliamo eseguire un’azione al momento del logout, i comandi vanno inseriti nel
file .bash logout che si trova nella home directory dei vari utenti.
Tipico esempio: si possono aggiungere alla fine del file .bash logout i comandi:
echo ‘‘Arrivederci $LOGNAME, premi un tasto per uscire...’’
read
.bash logout è l’ultimo file che viene eseguito prima di terminare una sessione
(tramite il comando exit).
81
Concetti Avanzati
82
Ancora sui parametri di uno script. Il comando shift
Il comando shift serve per spostare di una posizione verso sinistra i parametri di
uno script. Ad esempio, se in un determinato istante i parametri si trovano nella
posizione
$1 = -f, $2 = foo, $3 = bar
e si esegue il comando shift, successivamente i parametri si troveranno nelle posizioni:
$1 = foo, $2 = bar
83
Per chiarirsi le idee, scrivere il seguente script:
echo ‘‘I parametri prima dello shift sono: \$1=$1, \$2=$2, \$3=$3’’
shift
echo ‘‘I parametri dopo lo shift sono: \$1=$1, \$2=$2, \$3=$3’’
Se lo script è contenuto in un file che si chiama esempio.sh, eseguirlo nel seguente
modo:
$ chmod +x esempio.sh
$ ./esempio.sh -f foo bar
I parametri prima dello shift sono $1=-f, $2=foo, $3=bar
I parametri dopo lo shift sono $1=foo, $2=bar, $3=
84
Si possono anche spostare i parametri di più di una posizione, specificando un numero
come parametro del comando shift. Ad esempio, il comando
shift 2
sposta i parametri di due posizioni (sempre verso sinistra).
85
A cosa serve il comando shift?
Serve per parsare i parametri!!
Ad esempio, supponiamo di voler scrivere uno script (contenuto in un file di nome
dividi) che riceve un numero x (tramite l’opzione -up) e un numero y (tramite
l’opzione -down) e calcola x/y.
Inoltre supponiamo di voler potere eseguire lo script in entrambi questi modi:
$ ./dividi -up 500 -down 5
$ ./dividi -down 5 -up 500
in entrambi questi casi (ovvero indipendentemente dall’ordine dei parametri) lo script
deve eseguire la divisione di 500 per 5.
L’unico modo è scandire i parametri in cerca delle opzioni -up e -down.
86
Script dividi
while [ "$1" ]
do
if [ "$1" = "-up" ]
then
num=$2
shift 2
elif [ "$1" = "-down" ]
then
den=$2
shift 2
else
echo "Opzione $1 non riconosciuta"
exit 1
fi
done
echo "Risultato: ‘expr $num / $den‘"
87
Comando getopts
Il comando getopts serve per gestire le opzioni che vengono passate a uno script.
Sintassi:
getopts
<stringa-di-opzioni>
<nome-di-variabile>
<stringa-di-opzioni> contiene le lettere che identificano le opzioni che devono
essere riconosciute.
Se una di queste lettere è seguita dal simbolo “:”, ci si aspetta che l’opzione abbia
un argomento, che deve essere separato dalla lettera tramite un carattere di spazio
bianco.
88
Ogni volta che è invocato, getopts mette la prossima opzione nella variabile di shell
<nome-di-variabile>.
Quando un’opzione richiede un argomento, getopts memorizza l’argomento nella
variabile OPTARG.
Se viene data un’opzione tramite una lettera che non rientra in stringa-di-opzioni>,
getopts memorizza il carattere ? in <nome-di-variabile>.
89
Esempio
Il seguente script stampa gli argomenti di ogni opzione. Supponiamo che esso sia
memorizzato in un file di nome esempio, il suo funzionamento è:
$ ./esempio
Argomento
Argomento
Argomento
Argomento
-a opzione1 -b opzione2 -c opzione3 -d opzione4
dell’opzione a: opzione1
dell’opzione b: opzione2
dell’opzione c: opzione3
dell’opzione d: opzione4
90
while getopts a:b:c:d:
do
case "$opt" in
a)
b)
c)
d)
*)
esac
done
echo
echo
echo
echo
"Argomento
"Argomento
"Argomento
"Argomento
opt
oa="$OPTARG";;
ob="$OPTARG";;
oc="$OPTARG";;
od="$OPTARG";;
echo "errore";;
dell’opzione
dell’opzione
dell’opzione
dell’opzione
a:
b:
c:
d:
$oa"
$ob"
$oc"
$od"
91
Selezionare porzioni di un file tramite l’utility cut
Supponiamo di avere, all’interno di un file di testo chiamato studenti le due
seguenti colonne, separate dal carattere TAB:
1
2
3
4
Rossi
Bianchi
Verdi
Gialli
Tramite il comando cut usato con l’opzione -f posso selezionare e stampare a video
una colonna:
$ cut -f1 studenti
1
2
3
4
92
Analogamente, posso selezionare e stampare la seconda colonna come segue:
$ cut -f2 studenti
Rossi
Bianchi
Verdi
Gialli
93
Concatenare le righe di un file tramite l’utility paste
Supponiamo di avere i due files seguenti: il file studenti che contiene:
1
2
3
4
Rossi
Bianchi
Verdi
Gialli
ed il file voti che contiene:
1
2
3
4
30
21
27
24
94
Tramite il seguente comando si ottiene il seguente risultato:
$ paste studenti voti
1
Rossi
1
30
2
Bianchi
2
21
3
Verdi
3
27
4
Gialli
4
24
95
Si può mettere insieme l’effetto del comando cut con quello del comando paste
per ottenere risultati più sofisticati:
$ cut -f2 studenti > tmp1
$ cut -f2 voti > tmp2
$ paste tmp1 tmp2
Il risultato è:
Rossi
Bianchi
Verdi
Gialli
30
21
27
24
96
L’utility join
Adesso scriviamo il seguente comando e otteniamo il seguente risultato:
$ join studenti
1
Rossi
2
Bianchi
3
Verdi
4
Gialli
voti
30
21
27
24
join cerca gli elementi della prima colonna di un file e li matcha con quelli della
prima colonna di un altro file (senza ripeterli nel risultato).
Funziona solo se ci sono dei campi comuni in entrambi i files e se sono identici.
97
L’utility tr
Il comando seguente comando restituisce il seguente risultato:
$ tr ‘‘s2’’ ‘‘3x’’ < studenti
1
Ro33i
2
Bianchi
x
Verdi
4
Gialli
Ogni occorrenza del carattere“s”è stata sostituita col carattere“3”, ogni occorrenza
del carattere “2”è stata sostituita col carattere “x”.
98
L’utility tr può lavorare anche sui range.
Scrivere sulla riga del prompt:
$ tr ‘‘[a-z]’’
ciao a tutti
CIAO A TUTTI
che magia!
CHE MAGIA!
‘‘[A-Z]’’
(per uscire fare control-C).
99
Manipolare i file con l’utility awk
Si consideri un file chiamato spesa che contiene:
prosciutto
torta
minestrone
formaggio
frutta
stagionato
fresco
surgelato
fresco
fresco
4
10
4
12
5
Il seguente comando da il seguente risultato:
$ awk ’/fresco/ {print $3}’ spesa
10
12
5
Seleziona ogni riga che contiene la parola fresco e stampa il terzo campo.
100
Find and replace tramite l’utility sed
Si consideri un file chiamato frase contenente il seguente testo:
Il vino italiano è buono.
La birra tedesca è buona.
La birra è meglio del limoncello.
Il seguente comando restituisce il seguente risultato:
$ sed ’/birra/s//grappa/g’ frase
Il vino italiano è buono.
La grappa tedesca è buona.
La grappa è meglio del limoncello.
/birra/ significa “trova la parola birra”
s//grappa significa “rimpiazzala con la parola grappa”
g significa che l’operazione deve essere effettuata globalmente (su tutto il file).
101
Eliminare le righe ripetute tramite l’utility uniq
Dato il file (di nome frase):
Ciao a tutti
1234
1234
Il comando seguente restituisce il seguente risultato:
$ uniq frase
Ciao a tutti
1234
Per ordinare un file e poi eliminare le righe ripetute, si può fare:
$ sort <nome-file> | uniq
102
Selezionare righe con una parola tramite l’utility grep
Dato il file (di nome frase):
Ricordati di studiare
altrimenti sono guai
è difficile capire
ma ci riuscirai
Il comando seguente restituisce il seguente risultato:
$ grep ‘‘di’’ frase
Ricordati di studiare
è difficile capire
Sono state restituite le righe in cui compare la stringa“di”anche come parte di una
parola.
103
Esercizi
104
Esercizio 1
Scrivere uno script che riceve in ingresso due numeri (digitati dall’utente) e ne stampa
a video la somma.
105
Svolgimento 1
if [$# -ne 2]
then
echo ‘‘Questo script si usa cosi:’’
echo ‘‘$0 x y’’
echo ‘‘dove x e y sono due numeri da sommare’’
exit 1
fi
echo ‘‘La somma di $1 piu $2 è uguale a ’expr $1+$2’ ‘‘
Se il file si chiama somma:
$ chmod 755 somma
$ somma
Questo script si usa cosi:
somma x y
dove x e y sono due numeri da sommare
$ somma 10 5
La somma di 10 piu 5 è uguale a 15
106
Esercizio 2
Scrivere uno script che consenta di eseguire le operazioni aritmetiche di:
• somma
• sottrazione
• moltiplicazione
• divisione
Se il nome del file che contiene lo script è operazioni, lo script deve funzionare
cosı̀:
$ ./operazioni 20x3
Il risultato è 60
107
Svolgimento 2
if test $# = 3
then
case $2 in
+) let z=$1+$3;;
-) let z=$1-$3;;
/) let z=$1/$3;;
x|X) let z=$1*$3;;
*) echo ‘‘Attenzione: $2 è un operatore non valido.’’
echo ‘‘solo +,-,x,/ sono operatori validi.’’
exit 1;;
esac
echo Il risultato è $z
else
echo ‘‘Usage: $0 valore1 op valore2’’
echo ‘‘Dove valore1 e valore2 sono numeri’’
echo ‘‘e op è uno tyra i simboli +,-,x,/’’
fi
108
Esercizio 3
Scrivere uno script che permetta di visualizzare a video la data, l’ora, il nome
dell’utente e la directory corrente.
109
Svolgimento 3
echo
echo
echo
echo
‘‘Hello $LOGNAME’’
‘‘Current date is ’date’ ‘‘
‘‘User is ’whoami’ ‘‘
‘‘Current directory is ’pwd’ ‘‘
110
Esercizio 4
Scrivere uno script che consenta di stampare a video i numeri in ordine inverso.
Ad esempio, se il numero è 123, lo script deve visualizzare 321.
111
Svolgimento 4
if [$# -ne 1]
then
echo ‘‘Usage: $0 n’’
echo ‘‘lo script stampa il reverse del numero n’’
exit 1
fi
n=$1
rev=0
sd=0
while [$n -gt 0]
do
sd=’expr $n % 10’
rev=’expr $rev \* 10 + $sd’
n=’expr $n / 10’
done
echo ‘‘Il reverse del numero è: $rev’’
112
Esercizio 5
Scrivere uno script che riceve in ingresso un numero e stampa a video la somma delle
sue cifre.
Ad esempio, se il numero è 123, lo script deve visualizzare 1+2+3=6.
113
Svolgimento 5
if [$# -ne 1]
then
echo ‘‘Usage: $0 n’’
echo ‘‘Lo script stampa la somma delle cifre del numero n’’
exit 1
fi
n=$1
sum=0
sd=0
while [$n -gt 0]
do
sd=’expr $n % 10’
sum=’expr $sum + $sd’
n=’expr $n / 10’
done
echo ‘‘La somma delle cifre è $sum’’
114
Esercizio 6
Scrivere uno script che controlla se nella directory corrente c’è un file il cui nome è
uguale alla stringa che ha ricevuto in ingresso.
115
Svolgimento 6
if [$# -ne 1]
then
echo ‘‘Usage: $0 file-name’’
echo ‘‘controlla l’esistenza di un file di nome file-name’’
exit 1
fi
if [ -f $1 ]
then
echo ‘‘il file $1 esiste!’’
else
echo ‘‘il file $1 non esiste’’
fi
116
Esercizio 7
Scrivere uno script che riceve una stringa e controlla se questa stringa contiene
o meno il simbolo “*”. Se lo contiene, stampare a video il messaggio “tutto ok”,
altrimenti stampare a video il messaggio “devi aggiungere il simbolo *”.
Esempio:
Supponiamo che il file che contiene lo script si chiami esercizio:
$ ./esercizio /bin
devi aggiungere il simbolo *
$ ./esercizio /bin/*
tutto ok
Attenzione: Risolvere l’esercizio senza usare cicli !
117
Svolgimento 7
if [$# -ne 1]
then
echo ‘‘Usage: $0 s’’
echo ‘‘controlla se la stringa s contiene il carattere *’’
exit 1
fi
cat ‘‘$1’’ > /tmp/file.$$
2> /tmp/file0.$$
grep ‘‘*’’
>
/tmp/file.$$
/tmp/file0.$$
if [$? -eq 1]
then
echo ‘‘devi aggiungere il simbolo *’’
else
echo ‘‘tutto ok’’
fi
rm -f /tmp/file.$$
rm -f /tmp/file0.$$
118
Esercizio 8
Scrivere uno script che stampi a video il contenuto di un file a partire da una certa
riga x e per un certo numero di righe n. Il nome del file, la riga di partenza x ed il
numero di righe da stampare n sono passati come argomento allo script.
Esempio
Supponiamo il file che contiene lo script si chiami esercizio e che il file myf abbia il seguente
contenuto:
Ciao,
oggi facciamo esercizi
di Sistemi Operativi.
Spero che sia divertente
e che serva ad imparare
il linguaggio di scripting
Allora:
$ ./esercizio 4 2 myf
Spero che sia divertente
e che serva ad imparare
Attenzione: Risolvere l’esercizio senza usare cicli !
119
Svolgimento 8
if [$# -ne 3]
then
echo ‘‘Usage: $0 x n nome-file’’
echo ‘‘stampa n righe del file nome-file a partire dalla riga x-esima’’
exit 1
fi
if [-e $3]
then
tail +$1 $3 | head -n$2
else
echo ‘‘Il file $3 non esiste’’
fi
120
Esercizio 9
Scrivere uno script che:
• Se riceve l’opzione -c esegue il clear dello schermo.
• Se riceve l’opzione -d mostra la lista dei file che sono presenti nella directory
corrente.
• Se riceve l’opzione -m mette in esecuzione mc (midnight commander shell), se
è installato.
• Se riceve l’opzione -e <nome-editor> apre l’editore <nome-editor>, se è
installato.
121
Svolgimento 9
#
#
#
Funzione per pulire lo schermo
cls()
{
clear
echo ‘‘Lo schermo è stato pulito. Premi un tasto per continuare...’’
read
return
}
122
#
#
#
Funzione che visualizza i file presenti nella directory corrente
show_files()
{
ls
echo ‘‘La lista dei file è stata visualizzata. Premi un tasto per continuare...’’
read
return
}
123
#
#
#
Funzione che fa partire il midnight commander shell
start_mc()
{
if which mc > /dev/null
then
mc
echo ‘‘Midnight commander shell eseguita. Premi un tasto per continuare...’’
read
else
echo ‘‘mc non installato! Premi un tasto per continuare...’’
read
fi
return
}
124
#
#
#
Funzione che mette in esecuzione un editore testuale
start_ed()
{
ced=$1
if which $ced > /dev/null
then
$ced
echo ‘‘$ced messo in esecuzione. Premi un tasto per continuare...’’
read
else
echo ‘‘$ced non installato. Premi un tasto per continuare...’’
read
fi
return
}
125
#
#
#
Funzione che stampa l’help del nostro script
print_help()
{
echo ‘‘Usage: $0 <opzione>’’
echo ‘‘Possibili opzioni:’’
echo ‘‘-c: pulisce lo schermo’’
echo ‘‘-d: mostra i files presenti nella directory corrente’’
echo ‘‘-m: mette in esecuzione il midnight commander shell’’
echo ‘‘-e <nome-editor>: mette in esecuzione l’editore <nome-editor>’’
return
}
126
#
#
#
Programma Principale
if [$# -eq 0]
then
print_help
exit 1
fi
while getops cdme: opt
do
case $opt in
c) cls;;
d) show_files;;
m) start mc;;
e) nomeEditor=’’$OPTARG’’; start_ed $nomeEditor ;;
\?) print_help; exit 1;;
esac
done
127
Esercizio 10
Scrivere uno script che:
• Controlla se il parametro che gli viene passato è un file, una directory, oppure
non esiste e stampa questa informazione a video.
Poi scrivere uno script che:
• Stampa a video solo i nomi delle directory contenute nella directory corrente.
• Stampa a video solo i nomi dei file contenuti nella directory corrente.
• Stampa a video il numero di file e di directory contenuti nella directory corrente.
128
Svolgimento 10 - Prima parte
if [ -z \$1 ]
then
echo ‘‘Utilizzo: $0 nome di un file’’
exit 0
fi
if [ -f $1 ]
then
echo ‘‘$1 è un file’’
exit 0
fi
if [ -d $1 ]
then
echo ‘‘$1 è una directory’’
exit 0
fi
129
Svolgimento 10 - Seconda parte
#
#
#
Restituisce la lista di file
j=0
for i in ‘ls‘
do
if [ -f $i ]
then
echo $i
j=‘expr $j + 1‘
fi
done
echo ‘‘Ci sono $j file nella directory corrente’’
130
#
#
#
Restituisce la lista di directory
j=0
for i in ‘ls‘
do
if [ -d $i ]
then
echo $i
j=‘expr $j + 1‘
fi
done
echo ‘‘Ci sono $j directory nella directory corrente’’
131
Esercizio 11
Supponiamo di avere a disposizione un file chiamato fileDiDati che contiene il
seguente testo:
primo 3
secondo 10
terzo 25
quarto 2
quinto 12
Scrivere uno script che permette di stampare a video soltanto le linee per le quali il
valore numerico (che appare sulla seconda colonna) è superiore a 10.
132
Svolgimento 11
cat fileDiDati | while true
do
read ligne
if [ "$ligne" == "" ]
then
exit 0
fi
set -- $ligne
if [ $2 -ge 10 ]
then
echo -e "$1 \t $2"
fi
done
133
Esercizio 12
Si consideri un file di testo chiamato addizioni nel quale ogni linea contiene due
interi. Per esempio
2 7
3 13
1 28
...
Scrivere uno script chiamato somma che usa il file addizioni e produce il seguente
risultato:
$ ./somma < addizioni
2 + 7 = 9
3 + 13 = 16
1 + 28 = 29
...
134
Svolgimento 12
while read n1 n2
do
echo ‘‘${n1} + ${n2} = ‘expr ${n1} + ${n2}‘’’
done
135
Esercizio 13
Sulla base dell’esercizio precedente, scrivere uno script somma che usa il file addizioni
e produce il seguente risultato:
$ ./somma addizioni
2 + 7 = 9
3 + 13 = 16
1 + 28 = 29
...
136
Svolgimento 13
while read n1 n2
do
echo ‘‘${n1} + ${n2} = ‘expr ${n1} + ${n2}‘’’
done < $1
137
Esercizio 14
Scrivere uno script che rinomina tutti i files con estensione .tex che sono presenti
nella directory corrente, facendo diventare la loro estensione .tex.old.
138
Svolgimento 14
for i in *.tex
do
mv $i $i.old
done
139
Esercizio 15
Scrivere uno script che rinomina tutti i files con estensione .tex che sono presenti
nella directory corrente, facendo diventare la loro estensione .TEX.
140
Svolgimento 15
for i in *.tex
do
mv $i ‘basename $i .tex‘ .TEX
done
141
Esercizio 16
Scrivere uno script che stampa a video la lista di tutti i file .html che sono presenti
nella directory corrente e scrive la prima linea di ogni file HTML in un file chiamato
File Heads
142
Svolgimento 15
echo ‘‘Lista dei files:’’
ls -lA
FILE_LIST=’’‘ls *.html‘’’
echo FILE_LIST: ${FILE_LIST}
RESULT=’’’’
for file in ${FILE_LIST}
do
FIRST_LINE=‘head -2 ${file}‘
RESULT=${RESULT}${FIRST_LINE}
done
echo ${RESULT} | cat >FILE_HEADS
echo ‘‘ ’$RESULT’ scritto.Tutto ok.’’
143