Forum Programmation.shell appliquer une action à chaque fichier d'un répertoire

Posté par  (site web personnel) .
Étiquettes : aucune
0
24
août
2006
Énoncé du problème : j'ai un nombre de fichiers auxquels je voudrais appliquer la même opération, le tout par l'intermédiaire d'un script.
Au début j'avais pensé à faire comme ceci :

#!/bin/sh
list=`ls *.jpg`
for i in $list
do
  macommande $i
done


Mais ça ne marche pas pour les fichiers qui ont des espaces dans leur noms.
Forcément si j'ai deux fichiers "fleur.jpg" et "chauve souris.jpg" il va vouloir me traiter trois fichiers appelés "fleur.jpg", "chauve" et "souris.jpg".

Voilà, si vous avez une méthode simple et efficace je suis preneur :)
Merci.
  • # ""

    Posté par  . Évalué à 5.

    macommande "$i"

    sinon find est ton ami.

    find . -type f -exec macommand '{}' \;
    • [^] # Re: "" => Pareil avec maxdepth et mindepth

      Posté par  . Évalué à 2.

      Bonjour,

      Juste pour ajouter que find peut travailler sur différents niveaux de profondeur (voir la page man/info).
      Donc, soit find parcourt un répertoire et tous ses sous-répertoires (cas par défaut), soit tu lui fixes des limites ;-)

      Cdlt,
    • [^] # Re: ""

      Posté par  . Évalué à 1.

      le coup des guillemets ne marche pas car le for recupere tous les séquences de lettres de $list ne contenant pas d'espaces.
      Du coup ton $i ne contient jamais d'espace et tu te retrouves au point depart.

      le find est bcp plus approprie
      • [^] # -print0

        Posté par  . Évalué à 2.

        Pour contourner tout type de caractères pénible (y compris guillemets et quotes): combiner "-print0" de find et "-0" de xargs, pour utiliser le caractère nul \0 comme séparateur.
        Apres tu peux faire un truc du genre:

        find . -maxdepth 1 -type f -name \*.jpg -print0 | xargs -0 -n 1 macommande


        (le -n1 de xargs servant à appeler la commande pour 1 fichier à la fois)
        De cette façon les noms de fichiers sont transmis via pipe à xargs et celui-ci construit directement les arguments de la commande, sans jamais passer par les interprétations éventuelles du shell.
    • [^] # Les guillemets c'est bien si on les met partout où c'est nécessaire

      Posté par  (site web personnel) . Évalué à 2.

      #!/bin/sh
      list=`ls *.jpg`
      for i in "$list"
      <-- guillemets
      do
         macommande "$i"
      <-- guillemets
      done


      ou plus simplement:

      #!/bin/sh
      for i in *.jpg
      do
         macommande "$i"
      <-- guillemets
      done


      Remplace macommande par un simple echo pour voir ce que ça donne...
  • # retirer_ces_$*%*&@_d'_espaces !!

    Posté par  . Évalué à 2.

    j'ai trouvé ce petit script bash pour retirer tous les espaces dans les noms de fichiers :


    for i in *" "* ; do
    j=`echo $i | sed -e 's/ /_/g' `
    mv "$i" "$j"
    done



    1. soit tu l'utilises pour retirer_ces_$*%*&@_d'_espaces !!
    2. soit tu le modifies pour l'inclure comme un filtre dans ton script (si c'est possible)
    3. soit tu l'utilises tel quel comme en 1, puis ton script, et retraite tes fichiers en inversant le sed ( sed -e 's/_//g' ) si tu veux rajouter ces *$%***@& d'espaces qui n'ont rien à faire dans un nom de fichier :)

    (désolé d'être grossier :) )

    Only wimps use tape backup: real men just upload their important stuff on megaupload, and let the rest of the world ~~mirror~~ link to it

    • [^] # Re: retirer_ces_$*%*&@_d'_espaces !!

      Posté par  . Évalué à 2.

      oui mais non, si tu fais le script inverse, un fichier qui contenait un tiret va se retrouver avec un espace.

      autant gérer le problème et mettre des guillemets autour de "$i"
      • [^] # Re: retirer_ces_$*%*&@_d'_espaces !!

        Posté par  (site web personnel) . Évalué à 1.

        Comme dit plus haut mettre des guillemets autour du $i ne change rien, c'est au niveau du for que c'est découpé au niveau des espaces, et même si je fais joujou pour mettre chaque nom de fichiers entre guillemets, ça me fait pareil (un fichier "chauve et un fichier souris.jpg").
        Le find fonctionne, mais ça reste problèmatique si je veux effectuer plus d'une commande, voir des tests, des boucles, avec le nom du fichier.

        Exemple pratique : renommer une série de photo par la date contenue dans les infos exif de l'image.
        Si il y a des photos prises en rafale, plusieurs photos auront le même nom (prises à la même seconde), donc il faut que je puisse gérer le cas où une photo ayant ce nom existe déjà, alors rajouter et incrémenter un nombre dans le nom.

        Je ne peux pas me contenter de faire un
        find -name "*.jpg" -exec mv '{}' `récuperer-la-date`.jpg
        Il faut que je puisse sortir une liste de fichier, et tous les traiter un par un comme je veux, pas que ce soit find qui exécute mes commandes (ce qui est assez limité).

        À la rigueur il y a peut être moyen de faire un ls *.jpg > /tmp/plop
        et pour chaque ligne du fichier /tmp/plop, faire mes traitements, mais comment lire ligne après ligne le fichier /tmp/plop ?
        En gros faire une boucle :

        tant_que pas fin du fichier $i = nouvelle ligne
          exécuter ceci
          tester cela et faire ça sinon faire ceci
        fin_tant_que

        Merci

        ce commentaire est sous licence cc by 4 et précédentes

        • [^] # Re: retirer_ces_$*%*&@_d'_espaces !!

          Posté par  . Évalué à 2.

          find -name "*.jpg" -exec macommand '{}' ;

          Tu sais, macommand peut très bien être un script qui fait ce que tu dis.

          par exemple. (largement améliorable)


          #!/bin/sh
          if [ -a "$1" ]; then
          date_exif=20061201
          new_name="$date_exif.jpg"
          counter="0"
          while [ -a "$new_name" ]; do
          counter=$[$counter+1]
          new_name="$date_exif-$counter.jpg"
          done
          mv "$1" "$new_name"
          else
          echo "paramètre incorrecte";
          exit -1;
          fi
  • # variable IFS du bash

    Posté par  . Évalué à 2.

    préciser IFS=$'\n' avant la formation de la liste fera que les éléments seront séparés par un retour à la ligne et pas des espaces. Il sera alors très simple de parcourir la liste sans se soucier des espaces.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.