====== Esercitazione 4 ======
===== Esercizio 1: ridefiniamo 'cd' =====
Ridefinire il builtin //cd// usando una **funzione cd** in modo che con 0 o 1 parametri si comporti come il
builtin //cd// mentre con 2 parametri, ad esempio:
cd old new
sostituisca tutte le occorrenze di //old// nella working directory corrente con //new// e poi cerchi di spostarsi nel
path cosi' generato (se esiste ed e' una directory).
Gestire anche le situazioni di errore. Utilizzare il costrutto //case// per discriminare fra il numero dei parametri
forniti alla funzione (vedi esempio nella lezione 3 su bash).
===== Esercizio 2: icd, interactive cd =====
Definire la funzione **icd** (interactive cd) in modo che elenchi le directory presenti nella directory corrente e chieda inrterattivamente all'utente in qualse vuole spostarsi. Ad esempio:
bash:~$ icd
1) pippo/
2) pluto/
3) paperone/
Quale scegli?
3
bash:~/paperone$
Si usi il costrutto //select// per interagire con l'utente settando opportunamente la variabile di prompt.
Avanzato: estendere icd in modo che accetti come parametro il path della directory in cui effettuare la scelta.
===== Esercizio 3: printpath =====
Definire la funzione printpath che stampa una per linea tutte le directory presenti nella variabile di ambiente //PATH// (separatore ':') una per linea. Ad esempio
bash:~$ printpath
/home/susanna/bin
/usr/local/bin
/usr/bin
/usr/X11R6/bin
/bin
/usr/games
/opt/gnome/bin
/opt/kde3/bin
/home/susanna/local/bin
.
bash:~$
Attenzione: il separatore ':' deve essere rimosso.
===== Esercizio 4: printusr =====
Definire una funzione **printusr** che stampi i nomi dei primi 10 utenti della macchina ordinati lessicograficamente (vedi file /etc/passwd) con la loro home. Ad esempio
bash:~$ printusr
at:/var/spool/atjobs
bin:/bin
daemon:/sbin
francy:/home/francy
ftp:/srv/ftp
games:/var/games
gdm:/var/lib/gdm
irc:/usr/lib/ircd
ldap:/var/lib/ldap
lp:/var/spool/lpd
bash:~$
Chi riesce a farlo in meno linee di codice?
===== Esercizio 5: opzioni : mykeyselect =====
Scrivere uno script
mykeyselect [-a][-b barg][-c carg] file
//file// contiene su ogni riga delle coppie
chiave valore
dove ''valore'' e' un valore numerico. Lo script stampa la lista ordinata delle N chiavi di minor valore nel file. ''N'' e' pari a 4 se l'opzione ''-b'' non e' specificata altrimenti ''N=barg''. Se ''-a'' e' specificata si stampano le chiavi di maggior valore e non quelle di monor valore. Se e' specificata l'opzione ''-c'', vengono ignorate tutte le righe che contengono ''carg''.\\
Le gestione delle opzioni deve avere le seguenti proprieta':
* le opzioni possono essere fornite in un qualsiasi ordine ma sempre prima del nome del file (es:
mykeyselect -b 20 -a filename
mykeyselect -c -a -b 30 filename
* e' possibile specificare opzioni multiple con un singolo 'dash' (in questo caso solo l'ultima puo' avere un argomento opzionale). es:
mykeyselect -ac gigi
* e' possibile omettere lo spazio fra opzione ed argomento es:
mykeyselect -b20 -a filename
mykeyselect -cgigi -a -b 30 filename
mykeyselect -acgigi filename
//Suggerimenti: Utilizzare sort per effettare il sorting, in particolare verificare sul man le opzioni -n e -k. Utilizzare i builtin **shift** e **getopts** per effettuare il persing della linea di comando. Essendo builtin le informazioni in linea si possono accedere da **man bash**. Una spiegazione piu' accurata del funzionamento di getopts (con esempi) e' disponibile in linea [[http://www.mkssoftware.com/docs/man1/getopts.1.asp|qua]] oppure [[http://uw713doc.sco.com/en/man/html.1/getopts.1.html|qua]].//
===== Esercizio 6: interi : totdu =====
Sviluppare uno script:
totdu [ ... ]
che per ogni argomento che sia una directory stampa lo spazio utilizzato dalla directory e da tutte le sue sottodirectory, in byte e Kbyte (se >1KB) oppure in byte e Mbyte (se >1MB).
Se non viene specificata alcuna directory si forniscono informazioni sulla directory corrente. Ad esempio:
bash:~$ totdu ciccio pippo
ciccio: Totale 18098176 byte 17 MB
pippo: Totale 14336 byte 14 KB
//Suggerimenti: Utilizzare **du** per i byte occupati. Il comando **cut** puo' essere utile per selzionare un'opportuna colonna dell'output. Notare che nelle espressioni intere si puo' specificare un numero in base diversa da 10 con la notazione **base#numero** es: 16#400 per 1024.//
===== Esercizio 7: self exec shell =====
Provare ad eseguire:
#!/bin/bash
# self-exec.sh
echo "This line appears ONCE in the script, yet it keeps echoing."
echo "The PID of this instance of the script is still $$."
# The same shell always running
echo "==================== Hit Ctl-C to exit ===================="
sleep 1
exec $0
echo "This line will never echo!" # Why not?
exit 0
che succede? perche?
===== Esercizio 8: makecmd: a simple make =====
Implementare una funzione ''makecmd'' in grado di interpretare un singolo costrutto del tipo
target: source1 .. sourceN
cmd1
....
cmdK
fornito sullo standard input secondo la usuale semantica 'make' (la lista di comandi viene eseguita se il target non esiste oppure se e' stato modificato l'ultima volta in tempi precedenti rispetto ad almeno uno dei source nella dependency list, ogni comando viene prima stampato su stdout e poi eseguito). Se un source nella dependency list non esiste si considera la dipendenza verificata (!= semantica make).
Ad esempio:
bash:~$ more makefile
a : b c d
echo "Sto eseguendo!"
bash:~$ makecmd < makefile
echo "Sto eseguendo!"
Sto eseguendo!
Utilizzare il builtin ''read'' per leggere dallo standard input, ed ''eval'' per invocare la esecuzione di un comando della lista.