linux user group brescia

immagine del castello

Archivio della mailing list

[devnull a fastwebnet.it: qualche consiglio sullo shell scripting (was Re: nomi con gli spazi...)]

andrea gelmini andrea.gelmini a lugbs.linux.it
Dom 27 Apr 2003 13:12:24 UTC
vi rigiro un messaggio, girato in debian-italian. si affrontano una serie
di problematiche, legate agli shell script, sollevate tempo fa anche in
questa mailing list.
penso possa essere un buon sunto.

ciao,
andrea


----- Forwarded message from /dev/null <devnull a fastwebnet.it> -----

Date: Sat, 26 Apr 2003 20:36:53 +0200
From: /dev/null <devnull a fastwebnet.it>
To: debian-italian a lists.debian.org
Subject: qualche consiglio sullo shell scripting (was Re: nomi con gli spazi...)
X-Mailing-List: <debian-italian a lists.debian.org> archive/latest/37326

Premetto che il messaggio e` molto lungo e che contiene alcune
digressioni...

On Sat, Apr 26, 2003 at 02:16:29AM +0200, Guldo K wrote:
> Ragazzi, ho un n-esimo problemino, e sono di nuovo qui.
> Mi sono scritto uno script per automatizzare il resampling dei file audio, 
> eccolo qua:
Innanzitutto un suggerimento "generale": poiche' la shell e` ovviamente
il comando che si usa di piu` (anche solo perche' fa da "colla" tra
tutti gli altri comandi), secondo me il _primo_ manuale da leggere e`
proprio quello della shell stessa.

Ora sfrutto l'occasione di commentare lo script per dare qualche
suggerimento specifico.
> #!/bin/bash
> 
> if echo $1 | grep -iq '\-h'
Problema classico: dare come *argomento* (e non come opzione) ad un
comando una stringa che inizia col carattere "-". In questo caso
particolare mettere '\-h' funziona perche' "\" e` un metacarattere per
grep, e la regular expression "\-" _matcha_ la stringa "-".
La soluzione canonica (e "giusta" anche secondo lo standard POSIX),
comunque, e` mettere la stringa "--" prima degli argomenti (e quindi
dopo le eventuali opzioni): "--" segnala ai parser che la lista di
opzioni e` finita e che tutto cio` che segue sono argomenti.
Quindi potresti voler trasformare il comando in
	grep -iq -- -h
.
Detto questo, pero`, attenzione: se il nome di dest_dir contiene "-h" lo
script non fa la cosa giusta. Quindi si potrebbe affinare la regular
expression in modo da _matchare_ *solo* se $1 e` "-h" (e non se
semplicemente _contiene_ "-h"). Una regex per fare questo e` "^-h$'
(inizio riga seguito da "-" seguito da "h" seguito da fine riga).
Volendoti spingere oltre, potresti anche decidere che tutto sommato e`
legittimo avere una directory che si chiama "-h"... A questo punto
magari potresti verificare che come _unico_ argomento ci sia "-h":
	echo "$@" | grep -iq -- '^-h$'
...
Ma, come accennavo all'inizio, la soluzione migliore e` man bash: in
questo caso la descrizione del "builtin" getopts.

> then
>   echo 'sintassi: mp32wav dest_dir file1 file2 ...'
Una nota quasi puramente stilistica: siccome tu o qualche altro utente
dello script potrebbe volergli cambiare nome o creare un link simbolico
ad esso, puo` essere desiderabile usare `basename "$0"` anziche' mettere
"hardcoded" il nome attuale dello script.
	Nota quasi inutile: il comando basename e` reso inutile da
	alcuni costrutti POSIX, quali ${nome##pattern} e
	${nome%%pattern}. Ma, poiche' molte shell (non bash) non
	supportano ancora questi costrutti, usare basename e`
	accettabile.

> else
>   for T in $*; do
Questo e` uno dei motivi per cui lo script non funziona quando trova
degli spazi. Per usare gli argomenti rispettandone il quoting (NOTA:
quando dai gli argomenti devi _per forza_ proteggere gli spazi, come fa
altrimenti la shell a distinguere un nome con gli spazi da una sequenza
di nomi separati?) si usa il costrutto '"$@"' (virgolette doppie
incluse). Quindi:
	for T in "$@"
(in realta`, per passare a "for" la lista degli argomenti quotati, basta
il costrutto
	for T
ma questo e` poco importante).

>      if echo $T | grep -iq '.mp3'
non e` scorretto usare grep in questo caso (salvo per il fatto che echo
non ha un comportamento "rigoroso" qualora il primo argomento che riceve
inizi con "-"), ma forse il costrutto "case" e` meglio:
	case $T in
		*.mp3|*.MP3) eccetera ;;
		*) allora ;;
	esac
.

>      then
>         mpg123 -w ~/tmp.wav $T
Altro motivo per cui non funziona con gli spazi. Se una stringa puo`
contenere spazi bisogna sempre "quotarla", quindi:
	mag123 -v ~/tmp.wav "$T"
.

>         N=`basename $T ".mp3"`
Idem:
	N=`basename "$T" .mp3`
(inoltre: quotare ".mp3" e` inutile). Ma non basta. Se il nome contiene
spazi, anche il "basename" dello stesso puo` contenerne. Quindi va
quotato anche quello:
	N="`basename \"$T\" .mp3`"
(nota: bash e` _molto_ user friendly e avrebbe capito anche se noi
avessimo detto semplicemente "`basename "$T" .mp3`" (senza proteggere i
" interni con gli "\"), ma non consiglio di fare affidamento su questi
"candy").

>         if echo $1/ | grep -iq '//'
>         then
>            sox ~/tmp.wav -r 44100 -c 2 $1$N.wav
>         else
>            sox ~/tmp.wav -r 44100 -c 2 $1/$N.wav
>         fi
No, no: tutto questo e` inutile. E` "safe" metterci un "/" _anche se_ $1
contiene gia` un "/" alla fine. Dire "ls pippo/" e "ls pippo/////" e`
del tutto equivalente. Pero`, al solito, bisogna quotare:
	sox ~/tmp.wav -r 44100 -c 2 "$1"/"$N".wav
(si puo` anche quotare tutto insieme ("$1/$N.wav"), ma suona un po'
inelegante...).

>         rm ~/tmp.wav
Ah, a proposito del nome del file temporaneo: usarne uno fisso e`
insicuro. `man mktemp` contiene la soluzione a questo problema.

>      fi
>   done
> fi

Ciao,
/dev/null


-- 
To UNSUBSCRIBE, email to debian-italian-request a lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmaster a lists.debian.org

----- End forwarded message -----

-- 



Maggiori informazioni sulla lista Lug