Forum général.général Ligne de commande pour modifier un nom de fichier

Posté par  .
Étiquettes : aucune
0
14
mar.
2006
Bonjour,


Je ne connais pas grand chose aux lignes de commandes. Je me débrouille juste avec les commandes basiques style cp, rm, mkdir, apt-get, part-cache, dpkg, ls.... et la j'ai besoin de modifier les noms de quelques miliers de fichiers. La modification est simple : il s'agit de scouizer tous les caractères accentués et les remplacer par des caractère non-accentués. Par exemple il faudrait que tous les é, les è et les ê deviennent des e. Pareil pour les à qui doivent devenir des a et les ù qui doivent devenir des u. Ceci afin de rendre ces fichiers 100% compatibles avec n'importe quel système. Même avec un système germanique ou anglosaxon des années 40 ;-)
Je me suis dit que cela devait être faisable de manière automatisée avec quelques lignes de commande (un script ?). Malheureusement je ne vois pas comment faire. J'imagine que ca devrait commencer ainsi :

find /home/zebulon/dossier/*é*|/home/zebulon/dossier/*è*|/home/zebulon/dossier/*ê*|/home/zebulon/dossier/*à*|/home/zebulon/dossier/*ù* -exec rename {}

Mais arrivé la je sèche, et je suis meme pas sur que ca marche ce truc..... est-ce que quelqu'un peut me dire si je suis dans la bonne direction ou s'il vaut mieux que je retourne me coucher pour prendre des forces avant d'entammer le renommage de plus de 3000 fichiers à la main ?

Merci


Rénald
  • # en fait c'est facile

    Posté par  . Évalué à 2.

    ma vie:

    j'eu un excellent prof de physique, qui nous laisser faire des calculs de fourrier a la main pendant des semaines et des semaines. Puis un jour il arrive avec FFT au lieu de 4H tu mettais 10 minute. Tous le monde adoraient la nouvelle methode et elle et vite entré dans nos tetes.

    pour ton probleme:

    je t'encourage a en renommer une centaine à la main, ainsi tu vas comprendre comment devras faire le programme (script bash) pour trouver et remplacer ces caracteres. Une fois que tu en auras marre tu trouveras tout de suite la direction à prendre. et surtout tu liras attentivement le man awk ou le man sed
    • [^] # Re: en fait c'est facile

      Posté par  . Évalué à 8.

      Encore eut-il fallu que je connaisse l'existance de awk et de sed. Pour ta gouverne sache que ca fait des semaines que je renome des fichiers à la main (j'ai du en renommer environ 6000) et je doute que cette expérience ait pu m'aider à savoir ou à comprendre comment il est possible de faire la meme chose en quelques secondes avec une ligne de commandes.

      Si on ne connais pas l'existence d'une commande il me parait difficile de comprendre comment elle fonctionne. C'est pour cette raison que ce genre de forum existe il me semble : échanger ses connaissances et APPRENDRE. Un simple message notifiant l'existence de ces deux commandes aurait suffit. C'était pas la peine de jouer le grand professeur dédaigneux puant de science. A l'avenir, si un message ne te plais pas dans un forum, rien ne t'oblige à y répondre, tu passes au suivant et tu n'insulte personne.

      Merci quand même pour l'info.


      Rénald
      • [^] # Re: en fait c'est facile

        Posté par  . Évalué à 3.

        du calme, sache que pour ta gouverne personnel la plupart des demandes concernant le scripting unix comme la tienne ont toujours[1] une reponse qui propose la solution. car il y a toujours un petit concours derriere, mais qui va pondre un script le plus concis possible ? (enfin je dis ca en tant qu'habitué)

        je donnais juste mon point de vue ( sachant [1] ) enfin surtout la methode de mon prof de physique, mais tu me vois surpris de constater que tu as deja renomer 6000 sans faire du script ! bravo ! moi vers 200 ou 300 je reflechis a comment faire car ca me casse les bonbons.
  • # Plutôt une boucle ...

    Posté par  . Évalué à 5.

    En admettant que les fichiers sont tous dans le même répertoire, je ferais plutôt quelque chose comme :
    for i in `ls *`
    do
        j = `echo $i | tr "éèà" "eea"`
        echo mv $i $j
    done
    
    Evidemment pour le faire vraiment, décommente le echo (après vérification).
    • [^] # Re: Plutôt une boucle ...

      Posté par  . Évalué à 1.

      Très intéressantes les commandes tr et mv.
      Merci.

      Rénald
    • [^] # Re: Plutôt une boucle ...

      Posté par  . Évalué à 3.

      bravo, tu viens plus ou moins de recreer la commande ... rename
    • [^] # Re: Plutôt une boucle ...

      Posté par  . Évalué à 6.

      ça passera pas:

      - s'il y a trop de fichiers, `ls *` débordera
      - si les noms de fichiers contiennent un ou plusieurs espaces l'echo renvera une commande mv erronnée
      - s' il y a des doublons: il y aura des pertes: ex tété, tête (peu probable dans le même dossier)

      donc :

      - utiliser find "pipé" dans un xarg
      - utiliser les" autour de la variable $i et changer la variable d'environnement IFS : IFS=$'\n'
      - tester l'existence du fichier cible ou utiliser l'option -i de mv. (qui devrait déjà être un alias dans la plupart des systèmes)

      l'habitude de l'echo pour vérifier la justesse du script est une bonne astuce, il suffit ensuite de "piper" le script dans bash pour que l'exécution soit effective.


      ps: moi j'utilise le script rename présent dans la plupart des distributions.
      • [^] # Re: Ca passera pas

        Posté par  . Évalué à 1.

        Bon alors le premier paragraphe ca va, j'ai compris. j'ai meme compris jusqu'au premier mot "find". Par contre à partir du mot "pipé" ca deviens beaucoup plus flou.... Et alors quand tu parles de variable d'environnement, la je comprend plus rien !
        Par contre à la fin tu parles de rename J'ai donc fait un man rename et j'ai constaté avec regret qu'il fallait connaitre perl pour utiliser cette commande. Or je ne connais pas du tout ce language (j'en connais pas beaucoup en fait). Donc est-ce que tu as une idée de ce que je dois mettre comme expression dans la commande rename pour changer les "é" en "e" par exemple ? (on va simplifier la chose en ne s'occupant que des "é", je retaperai la commande pour les autres caractères).
        Merci pour ton aide.

        Rénald
        • [^] # Re: Ca passera pas

          Posté par  . Évalué à 3.

          pipé c'est comme un tube qui envoie les infos de sortie a un autre programme par exemple:
          la commande
          ls
          sort le contenu du repertoire
          maintenant tu voudrais voir uniquement les noms de fichier contenant 'log' tu utilise alors un autre programme adapté pour t'aider:

          ls | grep log

          note la barre verticale, c'est cela qui s'appelle un pipe, tu inject la sortie standard vers l'entrée standard. tu peux chainer:

          ls | grep log | grep a

          (je ne te dis pas cela pour me faire pardonner :) )
        • [^] # Re: Ca passera pas

          Posté par  . Évalué à 5.

          D'abord je me corrige, la commande à utiliser est xargs et non xarg...

          Le pipe: | est une redirection de flux de sortie de la commande se trouvant à sa gauche vers l'entrée de la commande se trouvant à sa droite, ex:

          frbn@deb:~$ find /usr/include -name string.h
          /usr/include/asm/string.h
          /usr/include/bits/string.h
          /usr/include/string.h
          ...


          si tu veux faire quelquechose avec ce que te renvoie la commande
          tu utilises le pipe:

          frbn@deb:~$ find /usr/include -name string.h | xargs du -h
          12K /usr/include/asm/string.h
          24K /usr/include/bits/string.h
          16K /usr/include/string.h
          ...


          La variable d'environnement IFS gère ce qui délimite les éléments d'une sélection par exemple dans une boucle for/do/done:

          $ ll
          total 0
          -rw-r--r-- 1 frbn frbn 0 2006-03-15 00:01 le_gros_truc
          -rw-r--r-- 1 frbn frbn 0 2006-03-15 00:01 le_petit_troc
          -rw-r--r-- 1 frbn frbn 0 2006-03-15 00:01 le petit truc

          $ for i in $(ls); do echo $i; done
          le_gros_truc
          le_petit_troc
          le
          petit
          truc

          tu remarqueras le fichier dont le nom contient des espaces n'est pas correctement sélectionné

          $ IFS=$'\n';for i in $(ls); do echo $i; done
          le_gros_truc
          le_petit_troc
          le petit truc

          là on est bon.

          Pour l'utilisation de rename, il est préférable de connaître les expressions rationnelle ou "régulières", j'utilise souvent un truc du genre de:
          rename 's/é/e/g' *.txt
          qui remplace tous les é par des e dans les fichiers, dont le nom se termine par .txt, du dossier courant...
  • # tr

    Posté par  . Évalué à 2.

    Je pense que ce qu'il te faut c'est `tr' .

    Une solution :
    for f in `find /home/zebulon/dossier/ -name "*[éèêàùûôîï]*"`; do
         g=`echo $f | tr éèêàùûôîï eeeauuoii`
         mv $f $g
    done


    PS : devrait fonctionner avec bash/sh. Pour tcsh, faudra utiliser la bonne syntaxe de la boucle for.
    • [^] # Re: tr

      Posté par  . Évalué à 1.

      Aaaaaargh trop lent !

Suivre le flux des commentaires

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