[shell] problème avec boucle find et espaces

Bonjour,
Petit soucis avec un script (qui doit remplacer le caractère  par _ dans tous les noms de fichier .jpg des sous répertoires du répertoire courant... pfiou !):
for f in `find . -type f -name "*.jpg" `; do
     mv -T "$f" "${f/Â/_}"
done


En fait, le soucis que j'ai, c'est que à un moment (peut-être dans le find), les noms des fichiers et des répertoires sont décomposés car ils contiennent des espaces et le shell me sort ca :
mv: ne peut évaluer `./300': Aucun fichier ou répertoire de ce type
mv: ne peut évaluer `de': Aucun fichier ou répertoire de ce type
mv: ne peut évaluer `Frank': Aucun fichier ou répertoire de ce type
mv: ne peut évaluer `Miller': Aucun fichier ou répertoire de ce type
mv: ne peut évaluer `2007/300': Aucun fichier ou répertoire de ce type
mv: ne peut évaluer `Comic': Aucun fichier ou répertoire de ce type
mv: ne peut évaluer `Con': Aucun fichier ou répertoire de ce type
mv: ne peut évaluer `2006/300Comicon_044.jpg': Aucun fichier ou répertoire de ce type
mv: ne peut évaluer `./300': Aucun fichier ou répertoire de ce type
mv: ne peut évaluer `de': Aucun fichier ou répertoire de ce type
mv: ne peut évaluer `Frank': Aucun fichier ou répertoire de ce type
mv: ne peut évaluer `Miller': Aucun fichier ou répertoire de ce type


Ca doit être bien facile à trouver, mais la... je bloque :(
QUelqu'un peut-il m'éclairer?

Merci d'avance!
Configuration: Windows Vista
Internet Explorer 7.0

14 réponses

  1. Modérateur
    Salut,

    En fait oui c'est bien une histoire d'espace, dû non pas à la commande "find" mais à la boucle "for" et plus particulièrement à la valeur de la variable d'environnement "$IFS" (Input Field Separator), qui par défaut a pour valeur l'espace et tabulation et à qui il faut assigner la valeur "saut de ligne" (\n) :
    OLD_IFS="$IFS"
    IFS=$'\n'
    for f in $(find . -type f -name "*.jpg"=; do
         mv -T "$f" "${f/Â/_}"
    done
    IFS="$OLD_IFS"
    Devrait marcher bien mieux.
    Sinon une autre façon de faire est passer par une boucle "while", voir à ce sujet cette astuce dans la FAQ.

    ;-))
    1. Ah super ! Merci, je connaissais pas ça... enfin c'est pas étonnant, j'ai raté quelques cours de shell :p
      Sinon j'ai un autre soucis du coup... j'aimerais remplacer le caractère ° par _ dans ma boucle précédente... mais on dirait que cela ne fonctionne pas, car aucun fichier n'est modifié... Pourtant j'utilise la même boucle :
      for f in `find . -type f -name "*.jpg" `; do
           mv -T "$f" "${f/°/_}"
      done
      1. Modérateur
        Il faut protéger l'étoile ( \* ) qui est un méta-caractère (ou joker si tu veux) afin qu'il ne soit pas interprété comme tel et lui rendre son sens littéral :
        mv -T "$f" "${f/\°/_}"
        ;-))
    2. En fait je dois être nouille mais cela ne marche pas :
      for f in `find . -type f -name "*.jpg" `; do
           mv -T "$f" "${f/\°/_}"
      done


      Aucun fichier n'est modifié :(

      Please help!!!
      1. Modérateur
        Attends là ! Faudrait qu'on se comprenne bien :-\

        Le caractère " * " se trouve bien dans le nom de tes fichiers ? Ou tu me parles d'autre chose !?
        [tmpfs]$ var="mon * étoile"
        [tmpfs]$ echo "$var"
        mon * étoile
        [tmpfs]$ echo ${var/\*/_}
        mon _ étoile
        [tmpfs]$  
        ;-)

        1. lol en fait non on se comprend pas bien, le caractère que je veux remplacer c'est un °, le ° de numéro ... :)
      2. Modérateur
        Arf désolé, problème d'affichage ;-((
        Bon mais en fait ça change pas grand chose :
        [tmpfs]$ var="mon n° à moi"
        [tmpfs]$ echo ${var/°/_}
        mon n_ à moi
        Si tu as des problèmes, affiches un exemple avec ton code et l'erreur générée.
        1. en fait voici mon code
          for f in `find . -type f -name "*.jpg" `; do
               mv -T "$f" "${f/°/_}"
          done


          ca marchait avec

          for f in `find . -type f -name "*.jpg" `; do
               mv -T "$f" "${f/Â/_}"
          done


          et là non :(
      3. Modérateur
        Et les noms de tes fichiers dans le répertoire ils ressemble à quoi ?

        Affiche un listing s'il te plaît "ls -1" (c'est un 1 (chiffre un) et pas un L minuscule, hein ?)
        1. Jury_n_°001.jpg
          Jury_n_°002.jpg
          Jury_n_°003.jpg
          Jury_n_°004.jpg
          Jury_n_°005.jpg
          Jury_n_°006.jpg
          ...
          Jury_n_°021.jpg
          Jury_n_°022.jpg
          
          1. Modérateur
            Ben je comprends pas non plus ;-\
            [tmpfs]$ touch Jury_n_°00{1,2,3,4,5}.jpg
            [tmpfs]$ ls -1
            Jury_n_°001.jpg
            Jury_n_°002.jpg
            Jury_n_°003.jpg
            Jury_n_°004.jpg
            Jury_n_°005.jpg
            
            [tmpfs]$ for f in *; do mv "$f" ${f/°/_}; done
            [tmpfs]$ ls -1
            Jury_n__001.jpg
            Jury_n__002.jpg
            Jury_n__003.jpg
            Jury_n__004.jpg
            Jury_n__005.jpg
            
            [tmpfs]$
            Essaie d'exécuter ton script en mode débogage, ajoute "set -xv" après la ligne "shebang" (#! /bin/bash) et essaie de repérer où ça coince...
            1. voila la sortie :

               for f in `find . -type f -name "*.jpg" `; do      mv -T "$f" "${f/\°/_}"; done
              for f in `find . -type f -name "*.jpg" `; do      mv -T "$f" "${f/\°/_}"; done
              find . -type f -name "*.jpg"
              ++ find . -type f -name '*.jpg'
              echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"
          2. Modérateur
            Salut,

            ça ne te conviens pas la commande rename ?
            rename 's/_\W/__/' Jury*.jpg
            1. Modérateur
              Ce n'est pas la peine d'échapper le "°" (${f/\°/_}), ce n'est pas un méta-caractère du shell !

              Il ne te renvoie que ça comme sortie le débogage ?
              Il en manque là, non ?
              1. heu non rename ca va pas trop, car les noms de fichiers sont jamais idnetiques, à part dans cet exemple....
                1. Modérateur
                  car les noms de fichiers sont jamais idnetiques, à part dans cet exemple
                  ben, justement, on peut utiliser les regex et c'est très puissant
                  si on reviens à ton problème de début remplacer le caractère  par _ dans tous les noms de fichier .jpg on aura ça

                  rename 's/\xC2/_/' *.jpg

                  1. ah ok !!! alors ca c'est correcte?

                    for f in `find . -type f`; do
                        rename 's/°/_/' *.jpg
                    done
                2. Modérateur
                  find . -name '*.jpg' -exec rename 's/°/_/' {} \;
                  mais il faut voir qu'il s'agit bien de °il faut voir le code ascii de ce caractère pour être sur qu'on cherche le bon caractère
                  1. en fait le soucis vient de là je pense, c'est que je n'utilisais pas le code ascii du caractère °...
                    Bon ben merci à tous, je vais tester cela, et je vous tiendrais au courant... histoire d'aider un jour un galérien comme moi :)