[gull] bash>for>word
Félix Hauri
felix at f-hauri.ch
Fri Oct 1 18:27:02 CEST 2004
On Fri, Oct 01, 2004 at 12:11:53PM +0200, Daniel Cordey wrote:
> On Friday 01 October 2004 11:40, Félix Hauri wrote:
>
> > Ok, mais là tu génère un fork en dehors duquel tes variables n'existent
> > plus! (Ou ne sont pas mises à jour)
>
> On s'en f... cette notion de variable n'est pas genante si tu te contente
> d'utiliser des valeusr a l'interieure du while. Definir le contenu d'une
> variable a l'interieur du while pour etre utilise dans le shell appelant
> n'est pa stres courant. En 22 ans de programmation shell, ca ne m'a jamais
> pose de probleme et on arrive toujours a s'en sortir.
> ...
> La boucle while n'est pas destinee a traiter juste une seule ligne... mais
> l'integralite du fichier, tel que :
>
> while read name passwd uid ...
> do
> echo ...
> done </etc/passwd
Prenons un cas pratique: La liste des ficher mp3 dans les répertoires
présents à mon niveau.
Partant du principe que tout les fichiers ont été compressé avec la même
commande, donc la sortie de la commande ``plaympeg'' donnera tjrs 4 lignes:
$ plaympeg --noaudio --novideo "Intégrale Vol.1/C'est l'histoire d'un mec...sur le pont de l'Alma.mp3"
C'est l'histoire d'un mec...sur le pont de l'Alma.mp3: MPEG audio stream
Audio MPEG-1 Layer 3 128kbit/s 44100Hz stereo
Size: 7806775
Total time: 487.923437
Que si j'essaie de ne lancer qu'une seule fois:
$ plaympeg --noaudio --novideo I*/* | grep "MPEG audio stream\|Total time"
Noël.mp3: MPEG audio stream
Total time: 145.729125
... ...
Y's foutent bien de notre gueule.mp3: MPEG audio stream
Total time: 333.732375
Elle ne me donne pas les noms des répertoires, je ne peux donc ``économiser''
les forks qu'au niveau des séries de fichiers présents dans 1 répertoire:
$ cnt=0 ;\
tot=0 ;\
x=${IFS} ;\
IFS=$':\n' ;\
for dir in I* ;do
plaympeg --noaudio --novideo ${dir}/* |
while read title dummy;
read dummy ;
read dummy ;
read dummy dure ;do
title=${title%.mp3}
printf "%-28s %-42s %7.2f\n" ${dir} ${title:0:42} $dure
tot=$(echo $tot+$dure|bc)
cnt=$((cnt+1))
done
done ;\
IFS=${x} ;\
printf "Total: %3d fichiers, %49s %8.2f\n" ${cnt} " " ${tot}
Intégrale Bonus Les inédits Noël 145.73
Intégrale Bonus Les inédits Oh ! Ginette 114.93
Intégrale Bonus Les inédits Reviens vas t'en 180.29
Intégrale Vol.1 C'est l'histoire d'un mec...sur le pont de 487.92
... ... ...
Intégrale Vol.6 PC GT - Russie-Pologne 251.68
Intégrale Vol.6 Y's foutent bien de notre gueule 333.73
Total: 0 fichiers, 0.00
Ça marche pas tant bien, dommage! ;-b
$ cnt=0 ;\
tot=0 ;\
x=${IFS} ;\
IFS=$':\n' ;\
for dir in I* ;do
set -- $(plaympeg --noaudio --novideo ${dir}/*)
while [ "$1" ] ;do
title=$1
shift 6
dure=$1
shift
title=${title%.mp3}
printf "%-28s %-42s %7.2f\n" ${dir} ${title:0:42} $dure
tot=$(echo $tot+$dure|bc)
cnt=$((cnt+1))
done
done ;\
IFS=${x} ;\
printf "Total: %3d fichiers, %49s %8.2f\n" ${cnt} " " ${tot}
Intégrale Bonus Les inédits Noël 145.73
Intégrale Bonus Les inédits Oh ! Ginette 114.93
... ... ...
Intégrale Vol.6 Y's foutent bien de notre gueule 333.73
Total: 76 fichiers, 22544.33
(Les ``read dummy'' ne sont pas forcement plus propre que le ``shift 6'';)
... et comme mes variable sont tjrs présentes, je peux encore:
$ date -ud "0:0:0 UTC +${tot%.*} secs" +%T.${tot#*.}
06:15:44.330424
Ou encore arrondir les secondes avec printf:
$ printf "0:0:0 UTC +%.0f secs" $tot | date -uf - +%T
06:15:44
> Un programme shell est avant tout destine a manipuler des fichiers. Un
> programme complexe destine a faire du traitement de variables doit etre
> realise dans un langage plus adapte.
Tu as raison, mais à partir de quel moment parle-t-on de ``programme complexe''?
> Pour ce faire, il y a des langage tout aussi lisibles et nettement plus
> appropries (Tcl, php, Python, ...)
Tu as encore raison, en Perl ce genre de truc est trivial ;-)
--
Félix Hauri - <felix at f-hauri.ch> - http://www.f-hauri.ch
More information about the gull
mailing list