Linux shell bash remplacer chaîne de caractère

Résolu
zatox19 Messages postés 31 Statut Membre -  
mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   -

Bonjour

Comment remplacer une chaîne de caractères par une autre dans les noms des dossiers sous-dossiers et fichiers d'un répertoire ? Je dis bien dans les NOMS que portent les dossiers sous-dossiers et fichiers.

Merci pour vos réponses.

11 réponses

  1. zatox19 Messages postés 31 Statut Membre 1
     

    Bonsoir,

    La commande qui marche chez moi c'est celle-ci:

    find . -type f,d -exec rename -va  $chaine1 $chaine2 {} \;

    Auparavant, j'ai trouvé pour connaître le nombre maximum de niveaux dans l'arborescence concernée avec cette commande :

    find 2>/dev/null | awk -F '/' '{print NF-1}' | sort -n | tail -n 1 > nb_niveaux.txt

    Dans ce cas le nombre de niveaux max se trouve dans nb_niveaux.txt ensuite il suffit de faire une boucle de 1 à nb_niveaux.txt et de passer dans la boucle la commande :

    find . -type f,d -exec rename -va  $chaine1 $chaine2 {} \;

    Merci pour votre aide, il y a peut-être mieux à faire mais cette solution me convient très bien.

    1
    1. mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   7 943
       

      Bonjour,

      Si ça peut te consoler, à mon avis, tu ne peux pas faire beaucoup mieux. En effet, rename ne modifie que 1 fichier au sens large (i.e., un dossier ou un fichier régulier). Donc si tu as N dossiers imbriqués et qu'il faut renommer chacun d'entre eux, alors N fichiers qui sont mis en jeu, et donc que tu dois faire N appels à rename.

      0
  2. dubcek Messages postés 18627 Date d'inscription   Statut Contributeur Dernière intervention   5 660
     

    hello

    voir man 1 rename

    0
  3. zatox19 Messages postés 31 Statut Membre 1
     

    Bonjour,

    Merci pour ta réponse. Effectivement, ça marche très bien, en se mettant dans le répertoire à l'intérieur duquel on veut renommer les dossiers et fichiers en remplaçant "chaîne1" des noms de fichiers et dossiers par "chaîne2".

    Exemple : je me mets dans le dossier /home/user/test-remplacer-choeur-par-chœur/ dans ce dossier j'ai ceci:

    [robert@rmageia9p1 test-remplacer-choeur-par-chœur]$ ls -l
    total 32
    drwxr-xr-x 2 robert robert 4096 août  10 10:42 choeur-choeurs-de-loups/
    -rw-r--r-- 1 robert robert    2 août  10 10:49 Choeur-de-de-loups.ods
    drwxr-xr-x 2 robert robert 4096 août  10 10:42 choeur-de-loups/
    -rw-r--r-- 1 robert robert    2 août  10 10:49 Choeur-de-loups.ods
    -rw-r--r-- 1 robert robert    2 août  10 10:49 choeur-de-loups.odt
    -rw-r--r-- 1 robert robert    2 août  10 10:49 choeur-de-loups.pdf
    -rw-r--r-- 1 robert robert    2 août  10 10:49 choeur-de-loups.txt
    drwxr-xr-x 2 robert robert 4096 août  10 10:42 haut-les-choeurs/

    Dans ce dossier je lance la commande :

    rename -vna choeur chœur *

    Voici ce que ça donne:

    [robert@rmageia9p1 test-remplacer-choeur-par-chœur]$ rename -vna choeur chœur *
    `choeur-choeurs-de-loups' -> `chœur-chœurs-de-loups'
    `choeur-de-loups' -> `chœur-de-loups'
    `choeur-de-loups.odt' -> `chœur-de-loups.odt'
    `choeur-de-loups.pdf' -> `chœur-de-loups.pdf'
    `choeur-de-loups.txt' -> `chœur-de-loups.txt'
    `haut-les-choeurs' -> `haut-les-chœurs'
    

    Si j'enlève l'option n à cette commande, elle me renomme bien mes fichiers et dossiers.

    Premier problème : je n'ai pas trouvé d'option pour dire de ne pas tenir compte des majuscules. Par exemple, pour "Choeurs", je suis obligé de lancer également la commande :

    rename -va Choeur chœur *

    Deuxième problème : j'aurais voulu traiter tous les répertoires afin de corriger l'intérieur de chaque répertoire. Style: boucle while ... par exemple ou autre. Il faudrait sans doute que j'écrive un script qui descendrait dans tous les dossiers et passerait la commande rename.

    En tous cas merci beaucoup pour ton aide.

    0
  4. dubcek Messages postés 18627 Date d'inscription   Statut Contributeur Dernière intervention   5 660
     

    pour ignorer la casse : /i

    rename -n 's/choeur/chœur/i'  

    pour parcourir l'arborescence

    shopt -s globstar
    rename -n 's/choeur/chœur/i' **/*

    PS : je n.'ai pas tout testé

    0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. zatox19 Messages postés 31 Statut Membre 1
     

    Bonjour,

    Merci pour cette réponse. Je ne connais pas shopt -s globstar.

    J'ai essayé de voir ce que ça fait mais je  n'ai pas compris. Il y a pas mal de temps que je n'avais pas trempé dans le shell bash...

    Par contre, ceci :

    rename -va $chaine_a_remplacer $chaine_de_remplacement *
    rename -va $chaine_a_remplacer $chaine_de_remplacement */*

    ... fonctionne, il faut que j'écrive un script qui récupère tous les sous-dossiers du répertoire concerné puis faire une boucle while dans chacun des répertoires et passer la commande rename. Certains penseront peut-être que ce n'est pas très élégant mais pour le moment je ne vois pas autre chose.

    Merci beaucoup pour votre aide.

    0
  7. dubcek Messages postés 18627 Date d'inscription   Statut Contributeur Dernière intervention   5 660
     

    on peut traiter chaque fichier d'une arborescence sans boucle

    remplacer  file par rename

    $ mkdir a b 
    $ touch a/a{1..3}
    $ touch b/b{1..3}
    $ 
    $ find *
    a
    a/a3
    a/a1
    a/a2
    b
    b/b3
    b/b1
    b/b2
    $ 
    $ shopt -s globstar
    $ file **/*
    a:    directory
    a/a1: empty
    a/a2: empty
    a/a3: empty
    b:    directory
    b/b1: empty
    b/b2: empty
    b/b3: empty
    $ 
    0
  8. zatox19 Messages postés 31 Statut Membre 1
     

    Bonjour,

    Merci pour ta réponse. J'ai écris ceci dans un script:

    #!/bin/bash
    
    repertoire="/home/robert/Bureau/test-remplacer-choeur-par-chœur/"
    cd $repertoire
    
    chaine1="choeur"
    chaine2="chœur"
    
    find *
    shopt -s globstar
    rename -va $chaine1 $chaine2 **/*

    Je veux donc changer la chaîne1 choeur par chœur, ça marche sur le premier niveau aussi bien concernant les noms de dossiers que les noms de fichiers. Mais si j'ai d'autres niveaux ça ne marche pas. J'ai pris un exemple où j'ai 7 niveaux, pour que ça marche il faut que j'appelle une fonction de ce style :

    remplacer_chaine () {
    
    rename -va $chaine1 $chaine2 *
    rename -va $chaine1 $chaine2 */*
    rename -va $chaine1 $chaine2 */*/*
    rename -va $chaine1 $chaine2 */*/*/*
    rename -va $chaine1 $chaine2 */*/*/*/*
    rename -va $chaine1 $chaine2 */*/*/*/*/*
    rename -va $chaine1 $chaine2 */*/*/*/*/*/*
    
    }

    Donc il faut que je fasse autant de rename que j'ai de niveaux, ce n'est pas top. De plus il faut d'abord que j'aille voir le nombre de niveaux pour répéter le rename. Bon j'ai trouvé cette solution mais ça ne me convient pas.

    Merci pour votre aide.

    0
  9. dubcek Messages postés 18627 Date d'inscription   Statut Contributeur Dernière intervention   5 660
     

    effectivement, shopt -s globstar est moins clair que je croyais

    essayer avec find

    find . -type f -exec rename -nva "s/$chaine1/$chaine2/" {} \;

    ps : je n'ai pas  la même commande rename que toi

    0
  10. zatox19 Messages postés 31 Statut Membre 1
     

    Bonjour,

    Merci pour cette réponse. J'avais essayé cette commande mais de mémoire c'est pareil, il me semble qu'il ne modifie que dans le répertoire courant ...

    Je viens de la passer mais j'ai une erreur :

    [robert@rmageia9p1 test-remplacer-choeur-par-chœur]$ find . -type f -exec rename -nva "s/choeur/chœur/" {} \;
    rename: pas assez d'arguments


    Merci

    0
  11. dubcek Messages postés 18627 Date d'inscription   Statut Contributeur Dernière intervention   5 660
     

    ps : je n'ai pas  la même commande rename que toi

    essaye avec tes options

    find . -type f -exec rename -nva  $chaine1 $chaine2 {} \;
    0
  12. zatox19 Messages postés 31 Statut Membre 1
     

    Bonjour, la commande qui marche:

    find . -type f,d -exec rename -va  "chœur" "choeur" {} \;

    Le seul problème c'est qu'il faut la lancer autant de fois qu'il y a de niveaux. Il faudrait que je puisse récupérer le nombre de niveaux maximum existant dans l'arborescence et boucler cette commande sur autant de niveaux

    Merci pour votre aide.

    0