Script Shell pour renommer plusieurs fichiers à partir du nom de leur dossier parent

J'ai une structure de fichiers comme celle-ci:

  • 00000010
    • 000000001.file1
    • 000000001.file2
  • 00000020
    • 00000003.file1
    • 00000003.file2
    • 00000003.file3

Il y a donc des dossiers avec des noms à 8 chiffres contenant un ou plusieurs fichiers avec un nom commençant par des nombres à 8 chiffres. Mais ces noms de fichiers sont – disons – hors synchronisation. Alors, j'essaie de les renommer récursivement en bash pour archiver:

  • 00000010
    • 000000010.file1
    • 000000010.file2
  • 00000020
    • 00000020.file1
    • 00000020.file2
    • 00000020.file3

Mon script ressemble à:

#! /bin/bash find * -maxdepth 1 -name "*" -type d | while read -r dir do rename 's/$dir\/[0-9]{8}/$dir/' * done 

Mais cela ne fonctionne pas et donne des erreurs comme

Le symbole global "$ dir" nécessite un nom de package explicite à (eval 1) ligne 1.

Comment puis-je l'écrire pour renommer les fichiers en fonction de leur nom de dossier?

Merci pour l'aide!

À partir d'une autre réponse, j'ai appris que je dois utiliser

 rename "s/$dir\/[0-9]{8}/$dir\/$dir/" $dir/* 

Juste au cas où quelqu'un aurait le même problème …

Je n'aime pas vraiment la réponse où $dir est interpolé dans le motif. Cela pourrait conduire à des résultats inattendus si le répertoire contenait par exemple un caractère qui est interprété comme un jeton regexp spécial.

Je préférerais combiner les fichiers directement dans le modèle, en annulant la nécessité de boucler les répertoires et d'utiliser un glob normal.

 rename 's#([^/]+)/[^/]+(\.file[0-9]+)$#$1/$1$2#' base_directory/*/* 

Où le glob obtient les fichiers individuels dans les répertoires (il pourrait même être spécifié dans base_directory/*/*.file* , ou similaire, mais cela ne devrait pas être important ici).

Notez que c'est la commande complète, sans avoir besoin de find construction.

  • J'utilise # comme séparateur au lieu du "régulier" / pour éviter d'avoir à échapper à celui dans les motifs.
  • Je capture le groupe (gourmand) de "pas un séparateur de répertoire", suivi d'un séparateur de répertoire, suivi d'un nom de fichier et d'une fin de ligne. Cela fait que le premier groupe de capture soit le répertoire parent pour chaque fichier.
  • La première partie du nom de fichier est rejetée, à l'exception de la fin de garder le suffixe ordinal.

J'ai choisi d'utiliser une approche plus générale que de supposer que les fichiers étaient tous de 8 caractères, mais la différence réelle est que je n'ai pas besoin de find construction ni de créer la variable $dir dans l'environnement de regexp (éventuellement dangereux).