Je souhaite renommer tous les fichiers et répertoires contenant le mot "spécial" en "normal". Il convient de conserver la sensibilité à la casse pour que "Spécial" ne devienne pas "normal".
Comment puis-je faire cela dans bash récursivement?
Essayez ceci (nécessite bash --version
> = 4):
shopt -s globstar
rename -n 's/special/regular/' **
Supprimez le commutateur -n
lorsque vos tests sont corrects
Il existe d'autres outils du même nom qui peuvent ou ne peuvent pas le faire, alors soyez prudent.
Si vous exécutez la commande suivante (GNU
)
$ file "$(readlink -f "$(type -p rename)")"
et vous avez un résultat comme
.../rename: Perl script, ASCII text executable
et ne contenant pas:
ELF
alors cela semble être le bon outil =)
Sinon, en faire la valeur par défaut (généralement déjà le cas) sur Debian
et ses dérivés comme Ubuntu
:
$ Sudo update-alternatives --set rename /path/to/rename
(remplacez /path/to/rename
par le chemin de votre commande Perl's rename
.
Si vous n'avez pas cette commande, recherchez votre gestionnaire de paquets pour l'installer ou faites-le manuellement
Last but not least, cet outil a été écrit à l'origine par Larry Wall, le père de Perl.
Une solution utilisant find
:
Pour renommer uniquement les fichiers :
find /your/target/path/ -type f -exec rename 's/special/regular/' '{}' \;
Pour renommer les répertoires uniquement :
find /your/target/path/ -type d -execdir rename 's/special/regular/' '{}' \+
Pour renommer les fichiers et les répertoires :
find /your/target/path/ -execdir rename 's/special/regular/' '{}' \+
Si l'installation d'un autre outil ne vous dérange pas, vous pouvez utiliser rnm :
rnm -rs '/special/regular/g' -dp -1 *
Il passera par tous les répertoires/sous-répertoires (à cause de -dp -1
) et remplacera special par regular dans leurs noms.
La réponse de @ speakr était l'indice pour moi.
Si vous utilisez -execdir pour transformer à la fois des fichiers et des répertoires, vous voudrez également supprimer -type f
de l'exemple présenté. Pour l'épeler, utilisez:
find /your/target/path/ -execdir rename 's/special/regular/' '{}' \+
Pensez également à ajouter un indicateur g
(global) à la regex si vous souhaitez remplacer toutes les occurrences de special
par regular
dans un nom de fichier donné et pas uniquement à la première occurrence. Par exemple:
find /your/target/path/ -execdir rename 's/special/regular/g' '{}' \+
transformera special-special.jpg
en regular-regular.jpg
. Sans l'indicateur global, vous obtiendrez regular-special.jpg
.
FYI: GNU Rename n’est pas installé par défaut sur Mac OSX. Si vous utilisez le gestionnaire de paquets Homebrew , brew install rename
remédiera à cela.
Pour ceux qui veulent juste renommer des répertoires, vous pouvez utiliser cette commande:
find /your/target/path/ -type d -execdir rename 's/special/regular/' '{}' \;
Le type de note est maintenant d
pour répertoire et utilise -execdir
.
Cependant, je n'ai pas réussi à savoir comment renommer les fichiers et les répertoires en un seul passage.
Quelqu'un a déjà fait remarquer qu’une fois le dossier racine renommé, il ne pouvait plus parcourir l’arborescence de fichiers. Il existe un commutateur -d
disponible qui effectue une traversée en profondeur de bas en haut, de sorte que la racine serait renommée en dernier, je crois:
find -d /your/target/path/ -type d -execdir rename 's/special/regular/' '{}' \;
Depuis la page de manuel (man find
):
-d Cause find to perform a depth-first traversal, i.e., directories are visited in post-order and all entries in a directory will be
acted on before the directory itself. By default, find visits directories in pre-order, i.e., before their contents. Note, the
default is not a breadth-first traversal.
Voici une autre approche plus portable qui fait not s'appuyer sur la commande rename
(car elle peut nécessiter des paramètres différents en fonction des distributions).
Il renomme récursivement les fichiers et les répertoires:
find . -depth -name "*special*" | \
while IFS= read -r ent; do mv $ent ${ent%special*}regular${ent##*special}; done
Ce qu'il fait
-depth
pour réorganiser les résultats en effectuant une traversée depth-first (c’est-à-dire que toutes les entrées d’un répertoire sont affichées avant le répertoire lui-même).De cette façon, les fichiers sont modifiés en premier, puis chaque répertoire parent.
Exemple
Donner l'arbre suivant:
├── aa-special-aa
│ └── bb-special
│ ├── special-cc
│ ├── special-dd
│ └── Special-ee
└── special-00
Il génère ces commandes mv
dans cet ordre particulier:
mv ./aa-special-aa/bb-special/special-cc ./aa-special-aa/bb-special/regular-cc
mv ./aa-special-aa/bb-special/special-dd ./aa-special-aa/bb-special/regular-dd
mv ./aa-special-aa/bb-special ./aa-special-aa/bb-regular
mv ./aa-special-aa ./aa-regular-aa
mv ./special-00 ./regular-00
Pour obtenir l'arbre suivant:
├── aa-regular-aa
│ └── bb-regular
│ ├── regular-cc
│ ├── regular-dd
│ └── Special-ee
└── regular-00