Aller au contenu

bash et regex - renommage de fichiers


luxian

Messages recommandés

Bonjour,

Je souhaite faire un script bash qui renomme une arborescence de fichiers selon tout un tas de petites règles à passer.
Mon gros problème est du type
find . -type f | rename 's/[ (1)]//' qui supprime tous les espaces de tous les noms de répertoires en plus du "(1)" ...


exemple :
- gicler les (1), (2) des anciens doublons qui n'en sont plus
- supprimer les "!", les "~", les "(" que le vulgus user crée dans ses fichiers word ou emails
- etc ...
Je ne veux pas de boucle while / for dans ce script ...
non, je n'en veux pas.
Mes commandes sont donc des regex (que je tente de commencer de comprendre), de l'usage de "rename", du "find", du "sed" (que j'entrave décidément pas depuis 3 h que je cherche) et du " | ".


Mes problèmes ...
Le plus gros :
Je n'arrive pas à faire comprendre à ma regex comment traiter non pas "chaque caractère" mais "une chaine". Notamment, la commande
find . -type f | rename 's/[ (1)]//gi'
... qui supprime tous les espaces de tous les noms de répertoires en plus du "(1)" ...
Je n'arrive pas à faire comprendre à "rename" (et d'ailleurs même sed), comment ne chercher que la chaîne " (1)" qui a "un espace" + "(1)" ... ou (2), etc ... à la fin du fichier. Je veux ici supprimer les doublons qu'a tendance à créer Google Drive quand il s'empêtre les synchronisations avec 3 PC connectés Windows au même google drive.


Et pour optimiser :
J'aurai bien aimé fusionner  == find . -type f | rename 's/é/e/gi' == et   == find . type f | rename 's/è/e/gi' == ... sans me retrouver avec ee dans le nom à chaque fois que j'ai un "é" ou un "è" :(  ... Je crois que j'ai testé toutes les combinaisons de  == find . type f | rename 's/[éè]/e/gi' == sans succès (cette combinaison écrit des "ee" à chaque "é" ou "è" et des "eeee" si le nom contient "éè" :-(

 


Précision, le système de fichier est ... ntfs / gvfs-fuse ... un répertoire Windows monté dans une machine virtuelle Ubuntu :)
Que fais-je donc ?
Je nettoie un Google-Drive, et une Dropbox lancée sous Windows 10 depuis une VM Ubuntu, et un disque dur de 2 To en 2 partitions (ntfs et ext4) monté quand à lui dans la dite VM Ubuntu :)

 

J'ai vu pas mal d'exemple avec des boucles type for / while etc ... Je n'en veux pas. Car il faut que je puisse réemployer facilement une même commande, mais avec des paterns différents à chaque fois.

Merci d'avance pour votre aide.

Lien vers le commentaire
Partager sur d’autres sites

Au lieu de:

find . -type f | rename 's/[ (1)]//gi'

Il doit falloir :

find . -type f | rename 's/ *(1)//gi'

 

Pour les regex

* = caractère précédant présent 0 fois ou plus

[0-9] = n'importe quel chiffre de 0 à 9

Donc tu pourrais faire ceci:

find . -type f | rename 's/ *([0-9])//gi'

Après la regex dépend un peu de la fonction utilisée (enfin d'où on l'utilise) et donc peu varier un peu.

 

find

find toto = chercher dans le répertoire toto

find -type f = chercher un fichier

 

Le |

Redirige ce qui est affiché à la fonction qui suit ce trait

 

sed

sed 's/abc/d/' = remplace le texte "abc" par "d" sur la première occurence (sed gère les regex)

 

rename

"rename - Rename or delete a command" <= d'après le man

Je me demande si tu ne confonds pas avec un "mv" (déplace mais sous le nom donné)

mv toto tata = renomme le fichier toto en tata

 

 

 

Lien vers le commentaire
Partager sur d’autres sites

J'ajoute que pour les regex, ( et ) sont des caractères reconnus, il faut les échapper (sauf si tu utilises sed...)

La syntaxe que tu indiques pour la regex est une syntaxe sed.

 

Voici un début pour sed:

$ echo "copy (1).jpg" | sed 's/\(.*\)\([ ](1)\)\(\..*\)$/mv "\1\2\3" "\1\3"/'

La syntaxe sed utilisée:

  • s/match/remplacement/options (je n'ai pas mis d'options, mais je crois que "i" signifie insensible à la casse)
  • Les \( et \) permettent de capturer des parties (qu'on rappelle ensuite par \1, \2, \3)
  • match: \(.*\)\([ ](1)\)\(\..*\)$
    • \(.*\): capturer n'importe quoi (\1 - nom du fichier)
    • \([ ](1)\): capturer " (1)" (\2)
    • \(\..*\)$: capturer l'extension (\3) (un point, n'importe quoi puis la fin de ligne ($))
  • remplacement:
    • mv "\1\2\3" "\1\3": remplacer le nom du fichier complet par le nom du fichier sans le " (1)"

A charge du lecteur de gérer tous les autres cas et de généraliser le " (1)" par une classe de caractères ou un intervalle.

 

 

Lien vers le commentaire
Partager sur d’autres sites

Archivé

Ce sujet est désormais archivé et ne peut plus recevoir de nouvelles réponses.

×
×
  • Créer...