[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