Lab. di Sistemi Operativi
Esercitazioni proposte per la lezione del 25 marzo 2011
Utilizzando la shell di Linux e disponendosi in gruppi di due persone per ogni PC del laboratorio.
1. Assegnare il nome assoluto della directory corrente alla variabile DIRCORR 2. Utilizzare il comando expr per sommare i numeri 10 e 12
3. Utilizzare il comando expr per moltiplicare fra loro i numeri 10 e 12
4. Creare una variabile d’ambiente di nome ”numero” ed assegnarle il valore 10. Sommare 12 a numero con il comando expr
5. Assegnare alla variabile numero il risultato di expr. Visualizzare l’exit value di expr.
6. Creare uno script (es41.sh) che accetti un numero di argomenti fra 1 e 3 compresi e che emetta un messaggio di errore su stdout in caso contrario
7. Modificare lo script precedente in modo che il messaggio di errore venga emesso su stderr 8. Come verificare che il messaggio viene realmente ridiretto su stderr?
9. Modificare nuovamente lo script es41.sh in modo che l’exit value del processo sia 0 in caso di successo o 1 in caso di errore
10. Creare uno script (es42.sh) che invochi lo script es41.sh con gli stessi argomenti con cui viene eseguito e che riporti su stdout l’exit value di es42.sh
11. Modificare ex42.sh in modo che es41.sh possa essere invocato come comando (senza ”./”) 12. Si analizzi la differenza fra l’aggiunta di pwd e l’aggiunta di . nel PATH
13. Dopo l’esecuzione di es42.sh, la variabile PATH della shell viene modificata?
14. A cosa serve export prima di PATH=?
15. Creare uno script (es43.sh) che visualizzi il nome dei file nella directory corrente, supponendo di non poter utilizzare il comando ls
16. Cosa avviene se invochiamo es43.sh in una directory vuota?
17. Modificare es43.sh in modo che visualizzi un messaggio appropriato se lo script viene invocato in una directory vuota
18. Facoltativo Credete sia possibile creare un file di nome *? Se si, come si comporterebbe es43.sh e come potremmo migliorarlo?
19. Modificare es43.sh in modo che stampi una F prima di ogni file regolare ed una D prima di ogni directory
20. Modificare es43.sh in modo da contare il numero di file regolari presenti, riportando questo valore nell’exit value
21. Riprendiamo es42.sh e modifichiamolo in modo che venga invocato es43.sh senza argomenti. Fatto questo, es43.sh diventer`a un comando e potr`a essere invocato qualunque sia la directory corrente del processo.
22. Modifichiamo es43.sh in modo che, per ogni directory trovata venga invocata una nuova istanza di es43.sh (processo figlio) in quella directory
23. Cosa avviene se invochiamo es43.sh senza utilizzare es42.sh?
24. Se cambiamo nome al file es43.sh, lo stesso non funziona pi`u: Modificarlo di conseguenza
25. Utilizziamo l’exit value dei processi figli in modo da contare tutti i file regolari presenti anche nelle sottodirectory
26. Progettare uno script (es44.sh) che visualizzi tutti i file della directory corrente ad eccezione di quelli che terminano con .sh
27. Modificare lo script precedente in modo che i file che terminano con .sh ma iniziano con es4 vengano visualizzati su stderr
28. Modificare lo script precedente in modo che visualizzi su stderr solo i nomi di file che iniziano con es4, terminano con .sh e non contengono la stringa #!/bin/sh
29. Completiamo lo script in modo che la ricerca di #!/bin/sh venga fatta solo sulla prima linea e che il carattere cancelletto # sia all’inizio della linea
30. Creare uno script (es45.sh) che riporti su stdout l’ultimo argomento della linea di comando
31. Creare uno script (es46.sh) che accetti un solo argomento e che verifichi se tale argomento rappresenta un nome assoluto
32. Modificare lo script es46.sh in modo che accetti un solo argomento e che verifichi se tale argomento rappresenta un nome relativo
33. Modificare lo script es46.sh in modo che accetti un solo argomento e che verifichi se tale argomento rappresenta un nome relativo semplice
34. (30 minuti) es47p.sh Controllo parametri della parte shell del compito del 7 luglio 2009: La parte in Shell deve prevedere due parametri: il primo deve essere il nome assoluto di un direttorio che identifica una gerarchia (G) allinterno del file system, mentre il secondo parametro deve essere un numero K strettamente positivo e pari. Il programma deve cercare nella gerarchia G specificata tutti i direttori che contengono un numero pari di file (solo file e non direttori) leggibili maggiore o uguale a K. Si riporti sullo standard output sia il nome assoluto di tali direttori che il numero di file F0...
FN-1 che soddisfano la condizione. In ogni direttorio trovato, si deve invocare la parte in C, passando come parametri i file F0... FN-1 trovati.
35. (30 minuti) es47r.sh Ricerca ricorsiva della parte shell del compito del 7 luglio 2009
Soluzione
Esercitazioni proposte per la lezione del 25 marzo 2011
Utilizzando la shell di Linux e disponendosi in gruppi di due persone per ogni PC del laboratorio.
1. Assegnare il nome assoluto della directory corrente alla variabile DIRCORR Soluzione:
$ DIRCORR=‘pwd‘
oppure
$ DIRCORR=$(pwd)
2. Utilizzare il comando expr per sommare i numeri 10 e 12 Soluzione:
$ expr 10 + 12 22
3. Utilizzare il comando expr per moltiplicare fra loro i numeri 10 e 12 Soluzione:
$ expr 10 * 12 expr: syntax error
$ expr 10 ’*’ 12 120
4. Creare una variabile d’ambiente di nome ”numero” ed assegnarle il valore 10. Sommare 12 a numero con il comando expr
Soluzione:
$ numero=10
$ expr $numero + 12 22
5. Assegnare alla variabile numero il risultato di expr. Visualizzare l’exit value di expr.
Soluzione:
$ numero=$(expr $numero + 12)
$ echo $?
0
$ echo $numero 22
# Attenzione: l’exit value del processo che ha eseguito
# expr vale 0, nulla a che fare con il risultato della
# espressione che vale 22 e viene riversato su stdout
6. Creare uno script (es41.sh) che accetti un numero di argomenti fra 1 e 3 compresi e che emetta un messaggio di errore su stdout in caso contrario
Soluzione:
#! / b i n / s h
i f t e s t $# − l t 1 −o $# −g t 3 then
echo E r r o r e n e l numero d i a r g o m e n t i f i
7. Modificare lo script precedente in modo che il messaggio di errore venga emesso su stderr Soluzione:
#! / b i n / s h
i f t e s t $# − l t 1 −o $# −g t 3 then
echo E r r o r e n e l numero d i a r g o m e n t i >&2 f i
8. Come verificare che il messaggio viene realmente ridiretto su stderr?
Soluzione:
Invocare lo script ridirigendo prima stdout poi stderr su /dev/null
9. Modificare nuovamente lo script es41.sh in modo che l’exit value del processo sia 0 in caso di successo o 1 in caso di errore
Soluzione:
#! / b i n / s h
i f t e s t $# − l t 1 −o $# −g t 3 then
echo E r r o r e n e l numero d i a r g o m e n t i >&2 e x i t 1
f i e x i t 0
10. Creare uno script (es42.sh) che invochi lo script es41.sh con gli stessi argomenti con cui viene eseguito e che riporti su stdout l’exit value di es42.sh
Soluzione:
#! / b i n / s h . / e s 4 1 . sh $ ∗ echo $ ?
11. Modificare ex42.sh in modo che es41.sh possa essere invocato come comando (senza ”./”) Soluzione:
#! / b i n / s h
export PATH=‘pwd ‘ : $PATH e s 4 1 . sh $ ∗
echo $ ?
12. Si analizzi la differenza fra l’aggiunta di pwd e l’aggiunta di . nel PATH Soluzione:
pwd viene espanso nel nome assoluto della directory corrente, quindi anche se si modifica la directory corrente dopo l’impostazione di PATH, sara’ possibile ancora invocare i comandi presenti.
se avessimo invece inserito la directory . allora la modifica alla
directory corrente renderebbe irraggiungibili i comandi, ma diventerebbero raggiungibili quelli nella nuova directory corrente
13. Dopo l’esecuzione di es42.sh, la variabile PATH della shell viene modificata?
Soluzione:
No. La variabile PATH che subisce la modifica e’ solo quella della sottoshell.
14. A cosa serve export prima di PATH=?
Soluzione:
La variabile di ambiente PATH viene inserita nell’elenco delle variabili da passare ai processi figli. Normalmente PATH viene marcata in questo modo gia’ dagli script di configurazione della shell (.profile e derivati) ma ... non sempre!
15. Creare uno script (es43.sh) che visualizzi il nome dei file nella directory corrente, supponendo di non poter utilizzare il comando ls
Soluzione:
#! / b i n / s h
f o r f i l e n a m e i n ∗ do
echo $ f i l e n a m e done
16. Cosa avviene se invochiamo es43.sh in una directory vuota?
Soluzione:
Viene visualizzato il carattere *, quindi la shell lascia il wild card * inalterato se non puo’ espanderlo
17. Modificare es43.sh in modo che visualizzi un messaggio appropriato se lo script viene invocato in una directory vuota
Soluzione:
#! / b i n / s h
f o r f i l e n a m e i n ∗ do
# t e s t e [ sono e q u i v a l e n t i a l 100%
# s e u s a t e [ , r i c o r d a t e d i m e t t e r e
# l a ] d i c h i u s u r a a l t e r m i n e i f [ $ f i l e n a m e = ” ∗ ” ]
then
echo D i r e c t o r y vuota e x i t 1
f i
echo $ f i l e n a m e done
e x i t 0
18. Facoltativo Credete sia possibile creare un file di nome *? Se si, come si comporterebbe es43.sh e come potremmo migliorarlo?
Soluzione:
#! / b i n / s h
# F a c o l t a t i v o cd $1
p i e n a=f a l s o
f o r f i l e n a m e i n ∗ do
i f [ ” $ f i l e n a m e ” = ’ ∗ ’ ] then
i f [ −e ’ ∗ ’ ] then
# ∗ e s i s t e , non v u o t a p i e n a=v e r o
f i e l s e
# f i l e n a m e non ∗ , non v u o t a p i e n a=v e r o
f i
echo ” $ f i l e n a m e ” done
i f [ $ p i e n a = f a l s o ] then
echo D i r e c t o r y vuota f i
e x i t 0
19. Modificare es43.sh in modo che stampi una F prima di ogni file regolare ed una D prima di ogni directory
Soluzione:
#! / b i n / s h
f o r f i l e n a m e i n ∗ do
i f [ $ f i l e n a m e = ” ∗ ” ] then
echo D i r e c t o r y vuota e x i t 1
f i
i f [ −f $ f i l e n a m e ] then
echo F $ f i l e n a m e f i
i f [ −d $ f i l e n a m e ] then
echo D $ f i l e n a m e f i
done e x i t 0
20. Modificare es43.sh in modo da contare il numero di file regolari presenti, riportando questo valore nell’exit value
Soluzione:
#! / b i n / s h c o n t a=0
f o r f i l e n a m e i n ∗ do
i f [ $ f i l e n a m e = ” ∗ ” ] then
# Dir v u o t a , 0 f i l e e x i t 0
f i
i f [ −f $ f i l e n a m e ] then
echo F $ f i l e n a m e
c o n t a =‘expr $ c o n t a + 1 ‘ f i
i f [ −d $ f i l e n a m e ] then
echo D $ f i l e n a m e f i
done
e x i t $ c o n t a
21. Riprendiamo es42.sh e modifichiamolo in modo che venga invocato es43.sh senza argomenti. Fatto questo, es43.sh diventer`a un comando e potr`a essere invocato qualunque sia la directory corrente del processo.
Soluzione:
#! / b i n / s h
export PATH=‘pwd ‘ : $PATH e s 4 3 . sh
echo $ ?
22. Modifichiamo es43.sh in modo che, per ogni directory trovata venga invocata una nuova istanza di es43.sh (processo figlio) in quella directory
Soluzione:
#! / b i n / s h c o n t a=0
f o r f i l e n a m e i n ∗ do
i f [ $ f i l e n a m e = ” ∗ ” ] then
# Dir v u o t a , 0 f i l e e x i t 0
f i
i f [ −f $ f i l e n a m e ] then
echo F $ f i l e n a m e
c o n t a =‘expr $ c o n t a + 1 ‘ f i
i f [ −d $ f i l e n a m e ] then
echo D $ f i l e n a m e cd $ f i l e n a m e e s 4 3 . sh cd . . f i
done
e x i t $ c o n t a
23. Cosa avviene se invochiamo es43.sh senza utilizzare es42.sh?
Soluzione:
L’invocazione delle sottoshell non funziona perche’ es43.sh non e’ un comando.
24. Se cambiamo nome al file es43.sh, lo stesso non funziona pi`u: Modificarlo di conseguenza Soluzione:
#! / b i n / s h c o n t a=0
f o r f i l e n a m e i n ∗ do
i f [ $ f i l e n a m e = ” ∗ ” ] then
# Dir v u o t a , 0 f i l e e x i t 0
f i
i f [ −f $ f i l e n a m e ] then
echo F $ f i l e n a m e
c o n t a =‘expr $ c o n t a + 1 ‘ f i
i f [ −d $ f i l e n a m e ] then
echo D $ f i l e n a m e cd $ f i l e n a m e
$0 cd . . f i
done
e x i t $ c o n t a
25. Utilizziamo l’exit value dei processi figli in modo da contare tutti i file regolari presenti anche nelle sottodirectory
Soluzione:
#! / b i n / s h c o n t a=0
f o r f i l e n a m e i n ∗ do
i f [ $ f i l e n a m e = ” ∗ ” ] then
# Dir v u o t a , 0 f i l e e x i t 0
f i
i f [ −f $ f i l e n a m e ] then
echo F $ f i l e n a m e
c o n t a =‘expr $ c o n t a + 1 ‘ f i
i f [ −d $ f i l e n a m e ] then
echo D $ f i l e n a m e cd $ f i l e n a m e
$0
c o n t a =‘expr $ c o n t a + $ ? ‘ cd . .
f i done
e x i t $ c o n t a
26. Progettare uno script (es44.sh) che visualizzi tutti i file della directory corrente ad eccezione di quelli che terminano con .sh
Soluzione:
#! / b i n / s h
f o r f i l e n a m e i n ∗ do
case $ f i l e n a m e i n
∗ . sh ) ; ;
∗ ) echo $ f i l e n a m e esac
done
27. Modificare lo script precedente in modo che i file che terminano con .sh ma iniziano con es4 vengano visualizzati su stderr
Soluzione:
#! / b i n / s h
f o r f i l e n a m e i n ∗ do
case $ f i l e n a m e i n
e s ∗ . sh ) echo $ f i l e n a m e >&2;;
∗ . sh ) ; ;
∗ ) echo $ f i l e n a m e esac
done
28. Modificare lo script precedente in modo che visualizzi su stderr solo i nomi di file che iniziano con es4, terminano con .sh e non contengono la stringa #!/bin/sh
Soluzione:
#! / b i n / s h
f o r f i l e n a m e i n ∗ do
case $ f i l e n a m e i n
e s ∗ . sh ) cat $ f i l e n a m e | g r e p ’#! / b i n / sh ’
# d a l l a man p a g e d i g r e p : t o r n a 0 s e almeno
# una l i n e a t r o v a t a , 1 s e n e s s u n a l i n e a ,
# 2 i n c a s o d i e r r o r e i f [ $ ? −eq 1 ]
then
echo $ f i l e n a m e >&2
f i
; ;
∗ . sh ) ; ;
∗ ) echo $ f i l e n a m e esac
done
29. Completiamo lo script in modo che la ricerca di #!/bin/sh venga fatta solo sulla prima linea e che il carattere cancelletto # sia all’inizio della linea
Soluzione:
#! / b i n / s h
f o r f i l e n a m e i n ∗ do
case $ f i l e n a m e i n
e s ∗ . sh ) cat $ f i l e n a m e | head −n 1 | g r e p ’ ˆ#! / b i n / sh ’ i f [ $ ? −eq 1 ]
then
echo $ f i l e n a m e >&2 f i
; ;
∗ . sh ) ; ;
∗ ) echo $ f i l e n a m e esac
done
30. Creare uno script (es45.sh) che riporti su stdout l’ultimo argomento della linea di comando Soluzione:
#! / b i n / s h
# S o l u z i o n e r a p i d a :
eval echo ‘ echo \ $ \{ $#\ } ‘
# S o l u z i o n e s e m p l i c e : i f [ $# −g t 0 ]
then
while [ $# −g t 1 ] do
s h i f t done
echo $1 e l s e
echo $0 f i
31. Creare uno script (es46.sh) che accetti un solo argomento e che verifichi se tale argomento rappresenta un nome assoluto
Soluzione:
#! / b i n / s h case $# i n
1 )
; ;
∗ )
echo Numero a r g o m e n t i e r r a t o e x i t 1
; ; esac
case ” $1 ” i n / ∗ )
; ;
∗ )
echo Nome non a s s o l u t o e x i t 1
; ; esac
32. Modificare lo script es46.sh in modo che accetti un solo argomento e che verifichi se tale argomento rappresenta un nome relativo
Soluzione:
#! / b i n / s h case $# i n
1 )
; ;
∗ )
echo Numero a r g o m e n t i e r r a t o e x i t 1
; ; esac
case ” $1 ” i n [ ˆ / ] ∗ )
; ;
∗ )
echo Nome non r e l a t i v o e x i t 1
; ; esac
33. Modificare lo script es46.sh in modo che accetti un solo argomento e che verifichi se tale argomento rappresenta un nome relativo semplice
Soluzione:
#! / b i n / s h case $# i n
1 )
; ;
∗ )
echo Numero a r g o m e n t i e r r a t o e x i t 1
; ; esac
case ” $1 ” i n [ ˆ / ] ∗ / ∗ )
echo Nome r e l a t i v o ma non s e m p l i c e e x i t 1
; ; [ ˆ / ] ∗ )
; ;
∗ )
echo Nome non r e l a t i v o e x i t 1
; ; esac
34. (30 minuti) es47p.sh Controllo parametri della parte shell del compito del 7 luglio 2009: La parte in Shell deve prevedere due parametri: il primo deve essere il nome assoluto di un direttorio che identifica una gerarchia (G) allinterno del file system, mentre il secondo parametro deve essere un numero K strettamente positivo e pari. Il programma deve cercare nella gerarchia G specificata tutti i direttori che contengono un numero pari di file (solo file e non direttori) leggibili maggiore o uguale a K. Si riporti sullo standard output sia il nome assoluto di tali direttori che il numero di file F0...
FN-1 che soddisfano la condizione. In ogni direttorio trovato, si deve invocare la parte in C, passando come parametri i file F0... FN-1 trovati.
Soluzione:
#! / b i n / s h
# S o l u z i o n e p r o v a d e l 7 l u g l i o 2009 − p r i n c i p a l e
# D a t i : $1−>G $2−>K
# C o n t r o l l o a r g o m e n t i ==2 case $# i n
2 ) ; ;
∗ ) echo Uso : $0 G K; e x i t 1 ; ; esac
# Assegnamento nomi G=” $1 ”
K=” $2 ”
# C o n t r o l l o G a s s o l u t o case ”$G” i n
/ ∗ ) ; ;
∗ ) echo G non a s s o l u t o : ”$G” ; e x i t 1 ; ; esac
# C o n t r o l l o G d i r e c t o r y e s i s t e n t e , l e g g i b i l e ed e s p l o r a b i l e i f [ ! −d ”$G” −o ! −x ”$G” ]
then
echo G non d i r e c t o r y e s p l o r a b i l e e x i t 1
f i
# C o n t r o l l o K numerico
expr ”$K” + 0 > / dev / n u l l 2>&1 case $ ? i n
0 ) ; ; # r i s u l t a t o != 0 1 ) ; ; # r i s u l t a t o == 0
2 ) echo K non num e ric o : ”$K” ; e x i t 1 ; ; # s y n t a x e r r o r , e s . K=’+’
3 ) echo K non num e ric o : ”$K” ; e x i t 1 ; ; # non−numeric argument , e s . K=’a ’ esac
# C o n t r o l l o K s t r e t t a m e n t e p o s i t i v o i f [ $K − l e 0 ]
then
echo K non s t r e t t a m e n t e p o s i t i v o : ”$K”
e x i t 1 f i
# C o n t r o l l o K p a r i
i f [ ‘ expr $K % 2 ‘ −ne 0 ] then
echo K non p a r i : ”$K”
e x i t 1 f i
# P r e d i s p o s i z i o n e e s e c u z i o n e export PATH=‘pwd ‘ : $PATH
# I n i z i o r i c e r c a e s 4 7 r . sh $G $K
35. (30 minuti) es47r.sh Ricerca ricorsiva della parte shell del compito del 7 luglio 2009 Soluzione:
#! / b i n / s h
# S o l u z i o n e p r o v a d e l 7 l u g l i o 2009 − r i c e r c a
# D a t i : $1−>d i r e c t o r y da e s p l o r a r e $2−>K cd $1
# R i c e r c a d i r e c t o r y c h e s o d d i s f a n o l a r i c h i e s t a c o n t a f i l e =0
l i s t a =” ”
f o r f i l e n a m e i n ∗ do
i f [ −f $ f i l e n a m e −a −r $ f i l e n a m e ] then
c o n t a f i l e =‘expr $ c o n t a f i l e + 1 ‘ l i s t a =” $ l i s t a $ f i l e n a m e ”
f i done
# C o n t r o l l o su c o n t a f i l e
i f [ $ c o n t a f i l e −ge $2 −a ‘ expr $ c o n t a f i l e % 2 ‘ −eq 0 ] then
echo Trovata d i r e c t o r y ‘pwd‘ con $ c o n t a f i l e f i l e parteC $ l i s t a
f i
# I n v o c a z i o n e r i c o r s i v a f o r f i l e n a m e i n ∗
do
i f [ −d $ f i l e n a m e −a −x $ f i l e n a m e ] then
$0 $ f i l e n a m e $2 f i
done