[prog-it] Re: Programmazione bash

  • From: "Seeman79" <Seeman79@xxxxxxxxx>
  • To: <prog-it@xxxxxxxxxxxxx>
  • Date: Thu, 01 Aug 2002 19:36:44 +0100


From: brain <xbrain@xxxxxxxxxx>
Subject: Re: Programmazione bash 
Date: Thu, 27 Jun 2002 02:03:17 +0200 

| Non si direbbe ma... si`, sono ancora vivo!! ;-P
In questo periodo capita di sparire; io, ad esempio,
tra impegni "seri", speleologia e barche non ho piu'
molto tempo disponibile.

| Dopo un lungo periodo di silenzio (ma di costante
| lettura) torno a postare...
Infatti mi chiedevo perche' non fossi intervenuto in
una discussione di un po' di tempo fa'...

| Ecco il problema: sto scrivendo uno script per
| semplificare la masterizzazione di cd audio;
Potrei farti notare che sarebbe necessario specificare
per quale sistema operativo e, a seconda della risposta,
potrei anche domandarti in che linguaggio (di scripting)
intendi realizzarlo... ma non te lo diro', per evitare
di essere troppo pignolo :)

| questo script deve effettuare tre operazioni:
| - verificare che ci sia abbastanza spazio su disco
Ho risolto il tuo "problema" (fossero questi i problemi :\).

| - estrarre tutte le tracce audio dal cd (cdparanoia -B)
Non credo che tu abbia bisogno di aiuto per questo passo e,
cmq, non ne hai richiesto. Solo una domanda:
conosci cdda2wav?

| - masterizzare il nuovo cd (cdrecord -v -eject ... )
Ottimo programma di masterizzazione.

| Il problema sta proprio nella prima:
Eh... immaginavo; le altre due sono solo la bieca scrittura
della riga di comando da usare in un file di testo :)

| pensavo di estrarre dall'output del comando df lo spazio
| libero,
E' originale come idea.

| ma... come si fa in bash?
Ti riporto piu' sotto lo script che ho fatto per risolvere
questo problema; ho cercato di farlo molto semplice (senza
usare sintassi strane e/o "avanzate"), e sotto lo script ti
ho scritto qualche riga di commento ma, se al termine della
lettura, qualcosa ancora non ti fosse chiaro chiedi pure
(come al solito... l'ho detta tante di quelle volte questa
frase che potrei anche darla per scontata).

| L'output di df e` una serie di righe di questo genere, una
| per ogni device montato:
| /dev/hda5             1.4G  155M  1.2G  11% /mnt/win_d
Non e' del tutto vero; in realta' oltre a queste linee, df,
stampa anche una riga (la prima) di "titolo" della tabella;
inoltre questo non e' proprio l'output STANDARD del comando
in oggetto, ma bensi' quello dovuto alla flag "-h" (serve
per avere un output comprensibile da noi umani... in realta',
a mio avviso, e' comprensibile anche quello standard, ma questa
e' la definizione che da' la pagina di man). 

| A me servirebbe il quarto dato, relativo allo spazio libero...
Eccoti lo script e, piu' sotto, i commenti.

==============================================================
#!/bin/bash

PARTIZIONE="/dev/hda2"
CD_LIM_MAX="650"
SPAZIO=""

liberi_tutti()
  {
     SPAZIO=`df -P -m | grep $PARTIZIONE`
     SPAZIO=`echo $SPAZIO | cut -f4 -d' '`

     if [ "$SPAZIO" = "" ]; then
       return 2
     elif [ `expr $SPAZIO - $CD_LIM_MAX` -gt 0 ]; then
       return 1
     else
       return 0
     fi
  }


liberi_tutti
TEMP=$?

case $TEMP in
   2) echo "$PARTIZIONE? Where is it?" ;;
   0) echo "$SPAZIO MB su $PARTIZIONE. Don't suck!" ;;
   *) echo "Let's start a war... said a Maggie one day." ;;
esac

exit $TEMP
==============================================================

Lo script risulta essere molto semplice e composto da tre parti
essenziali; all'inizio trovi la dichiarazione di tre variabili
globali, la prima delle quali definisce la partizione che ti
interessa, la seconda la capacita' del CD che devi andare a
copiare e la terza, inizializzata vuota, conterra' lo spazio
disponibile sulla partizione definita poco sopra.

Una prima osservazione che potresti fare e' che non ha senso
definire una variabile globale per una costante utilizzata solo
all'interno di una f(x); in parte cio' e' vero, ma la motivazione
per cui la definisco li' e' che la capacita' del tuo CD potrebbe
non essere 650 MB, magari di piu' o magari di meno e ti vedresti
costretto (in questo caso sarebbe poca fatica, ma in script piu'
corposi sarebbe un vero e proprio attentato alla tua pazienza) ad
andare a cercare questa costante per modificarla.

Una seconda buona osservazione che potresti fare sarebbe quella di
dirmi; "senti un po', cara la mia testa sciroppata, tante belle
parole ma questa implementazione non e' perfetta (non che tu l'abbia
mai detto... caro il mio carciofone), infatti cerca di seguirmi;
tralasciamo la possibilita' dei CD da 80 min e concentriamoci sul
fatto che in media la loro capacita' sia di 650 MB. Visto che stiamo
parlando di CD musicali, e' anche possibile che io voglia masterizzarmi
un "singolo", perche', allora, devo avere per forza liberi 650 MB
su disco quando in realta', esagerando, me ne servirebbero un centinaio?"

Tralasciando gli aggettivi che mi hai propinato, quali testa sciroppata
e carciofone (perche' sono veri e dunque non ho nulla da dire), ti posso
rispondere che hai perfettamente ragione; la risposta a questo quesito,
pero', la lascio a te sperando che il mio script ti serva da guida.

Continuando nella lettura dello script trovi la dichiarazione e
implementazione di una funzione chiamata "liberi_tutti". Questa funzione
ci permettera' di memorizzare in una variabile l'eventuale spazio libero
sulla partizione data e di capire se e dove si e' verificato un errore
(per come e' implementata potresti vederla come una funzione con SIDE
EFFECT).

Ragioniamo ora sui comandi che vengono lanciati; per esigenze di
omogeneita' (alle elementari dicevano che non puoi trattare patate e carote),
dobbiamo "forzare" il nostro programma (df) a mostrarci l'output in modo
consistente rispetto alla capacita' del cdrom; siccome la capacita' l'abbiamo
espressa in MB allora l'output dovra' essere necessariamente in MB.

Un'altra cosa da notare e' che, anche se df accetta da riga di comando la
partizione che a noi interessa, non gliela passo direttamente, ma faccio un
grep sull'output; la risposta a questa affermazione e' semplice in  quanto,
come ti facevo notare piu' sopra, df crea una "tabella" per i risultati e la
PRIMA riga e' SEMPRE un'intestazione. Passandogliela direttamente da riga di
comando, dunque, la nostra variabile SPAZIO non conterebbe solo la riga
interessata, ma anche l'intestazione. Al contrario, facendo un grep su tutto
l'output, riusciamo ad estrarre SOLO la riga che contiene il device della
nostra partizione (in bash con la sintassi `...` si memorizza l'output
del comando "..." in una variabile).

Ora che abbiamo la riga interessata (e solo lei) dobbiamo estrarre lo spazio
libero sulla partizione; per far cio' dobbiamo "tagliare" la stringa secondo
un token (come la strtok in C), in questo caso uno spazio (l'echo si occupera'
di eliminare gli spazi in eccesso). Per una spiegazione approfondita ti rimando
alle pagine di man del cut, ma qui ti spiego brevemente che cosa succede. Questo
e' l'output che abbiamo noi (nota che non abbiamo nessuna unita' di misura
espressa accanto ad ogni numero in quanto essa e' implicita a riga di comando):

/dev/hda5 1434 155 1229 11% /mnt/win_d

Se ora osservi questo schema capirai immediatamente (spero) come si usa il 
comando
cut:
                   
         _______token_______
         |    |   |    |   |
/dev/hda5 1434 155 1229 11% /mnt/win_d
    |      |    |   |    |      |
    1      2    3   4    5      6

Che cosa noti, infatti, in questo semplice schema oltre le mie pessime capacita'
come ASCII writer? Sicuramente puoi vedere come le parti della stringa siano
numerate progressivamente (e' possibile anche, tramite cut, restituire piu' 
parti
contemporaneamente) e che quindi a te interessa la numero 4. Ora, se tutto e' 
andato
bene, la variabile SPAZIO contiene quanto spazio e' ancora libero sulla 
partizione
data (in sole due righe di codice).

Passiamo ora a discriminare il risultato; ovviamente se tale variabile e' vuota 
c'e'
stato qualche problema (se, ad esempio, la partizione data non esiste, tale 
variabile
rimane vuota subito dopo il grep) e ritorniamo la costante intera positiva 2.
Altrimenti se contiene qualcosa, questo deve essere minore della capacita' del 
cd;
puoi confrontare la variabile con la costante in tanti modi; io ho scelto 
questo per
illustrarti anche il comando "expr"; cio' che faccio non e' complicato:
SPAZIO > CD_LIM_MAX  ==>  SPAZIO - CD_LIM_MAX > 0
Un po' di matematica spicciola; invece di controllare la prima condizione, 
controllo
la seconda che e' la stessa ma scritta in maniera differente.

Se questo controllo va a buon fine allora vuol dire che c'e' spazio a 
sufficienza e
ritorniamo 1, altrimenti non ce n'e' e ritorniamo 0; fine della funzione.

Ora inizia il "main" vero e proprio dello script; richiamo la funzione, 
memorizzo il
valore da lei ritornato in una variabile temporanea che vado poi a discriminare 
con un
"case" (ho volutamente "mischiato" la scala dei valori da processare per 
enfatizzare il
fatto che, almeno a livello pratico, cio' non compromette il nostro script). 
Nel mio
caso printo a video dei messaggi per l'utente ma tu, ovviamente, inserirai al 
posto
giusto i comandi da eseguire. Lo script infine ritorna un valore (cosa che 
dovrebbe
sempre fare), in questo caso, uguale a quello ritornato dalla funzione; in 
questo modo
quanto il tuo script sara' inserito di default nella tua distribuzione e lo 
potranno
usare anche altri utenti, quando lo richiameranno da altri script potranno 
sapere se
e' andato tutto bene con lo stesso "giochetto" della nostra variabile temp.

Come puoi notare la programmazione in bash non e' eccessivamente complicata ma 
e'
molto potente come strumento; l'unico requisito che bisogna avere e', forse, un 
po'
di fantasia per sfruttare tutto cio' a nostro vantaggio.

Alla prossima.
Ciao.

P.S. Ho volutamente NON risposto alla mail che risolveva il tuo problema in 
payton
     per manifesta incompatibilita' comunicativa tra i due soggetti. NON ho 
configurato
     il mio client per mandare la sua posta direttamente in "/dev/null", ho 
solo detto
     che non mi pare il caso di rispondere (non credo di venir meno ai miei 
principi in
     quanto in quella mail non ha richiesto nessun aiuto, ha solo espresso una 
sua
     opinione che posso condividere o non condividere, ma sicuramente posso 
ignorare
     in quanto non rivolta espressamente a me).
     Di questo, com'e' giusto che sia, non fregera' nulla a nessuno, ma e' una
     precisazione che ci tenevo a fare.


-- 
Se tutti ti vengono incontro, sei nella careggiata sbagliata.




Other related posts: