J'ai une structure de répertoire comme celle-ci:
Bookname Edition 1
Bookname Edition 1 type1.pdf
Bookname Edition 1 type2.pdf
Bookname Edition 2
Bookname Edition 2 type1.pdf
Bookname Edition 2 type2.pdf
Je veux changer de manière récursive le nom de Edition
en Volume
du répertoire et les noms de fichiers dans ces répertoires.
J'ai commencé avec ça et c'est bien si je suis dans le répertoire:
for f in *.pdf; do
a="$(echo $f | sed s/Edition/Volume/)"
mv "$f" "$a"
done
Ensuite, j'ai essayé de changer tous les fichiers sous les répertoires, et c'est à ce moment-là que je me suis retrouvé coincé ...
S'il vous plaît pouvez-vous me dire comment faire cela ou me donner un meilleur moyen de le faire. Il y a 15000 PDF dans 100 annuaires.
Si votre structure n'a que deux niveaux, vous n'avez pas besoin d'utiliser la récursivité.
Ne pas analyser les noms de fichiers avec sed
. Si vous souhaitez utiliser la syntaxe de style regex et sed
pour renommer les fichiers, utilisez rename
. Si vous utilisez Ubuntu 17.10, vous devez l’installer.
Sudo apt install rename
Ensuite, vous pouvez utiliser réponse de pa408 .
Avec rename
, utilisez l’option -n
pour le test.
rename -n 'expression' file(s)
Vous pouvez également simplement utiliser la commande mv
. En tant que commande d'une ligne:
for d in ./*/; do mv -v "$d" "${d/Edition/Volume}"; done; for f in ./*/*; do mv -v "$f" "${f/Edition/Volume}"; done
Vous pouvez utiliser echo
pour tester mv
, c'est-à-dire echo mv -v source dest
, mais cela donne des résultats inexacts ici, sauf si vous testez puis exécutez les boucles séparément.
En tant que script:
#!/bin/bash
# rename directories first
for d in ./*/; do
mv -v "$d" "${d/Edition/Volume}"
done
# now rename files
for f in ./*/*; do
mv -v "$f" "${f/Edition/Volume}"
done
mv
et rename
reconnaissent --
pour indiquer la fin des options. Puisque tous les chemins commencent par ./
dans cet exemple, nous n’avons pas besoin de l’utiliser, mais si les chemins peuvent commencer par -
, utilisez --
à la fin des options, par exemple rename -n -- 's/foo/bar/' *
, pour empêcher ces chemins d’être interprétés comme des options.
Vous pouvez utiliser la commande rename
à deux reprises pour accomplir cette tâche:
rename 's/Edition/Volume/' */ # rename the directories
rename 's/Edition/Volume/' */*.pdf # rename the PDF files inside
Voici deux questions similaires:
Sur les répertoires à plusieurs niveaux, vous pouvez le faire en une seule étape, mais le problème est que vous devez vous assurer de renommer les répertoires de bas en haut pour empêcher la commande ou le script de modifier le nom du répertoire avant que son contenu ne soit modifié.
En python, vous pouvez utiliser:
os.walk
en combinaison avec
topdown=False
Dans un script:
#!/usr/bin/env python3
import os
import shutil
import sys
for root, dirs, files in os.walk(sys.argv[1], topdown=False):
for f in files:
shutil.move(
root+"/"+f, root+"/"+f.replace("Edition", "Volume").strip()
)
for dr in dirs:
shutil.move(
root+"/"+dr, root+"/"+dr.replace("Edition", "Volume").strip()
)
Enregistrez le script sous change_name.py
, exécutez-le avec le répertoire comme argument:
python3 /path/to/change_name.py <directory>
Cela fonctionne de manière récursive sur n'importe quel nombre de niveaux.
Utilisez find
avec l'option -depth
associée à prename
:
find [DIRS...] -depth | prename -n 's|Edition(?=[^/]*$)|Volume|'
Explication:
-depth
sélectionne les enfants du répertoire avant leurs parents. Un outil "consommant" les noms de chemin sélectionnés pour renommer peut alors renommer les enfants avant leurs parents.
s|Edition(?=[^/]*$)|Volume|
remplace la première occurrence de Edition
dans le nom du chemin par Volume
mais uniquement si le reste ne contient pas un /
, i. e. il ne s'applique qu'au dernier composant du nom du chemin d'accès (obtenu par le code (?=[^/]*$)
positif).
-n
indique à prename
de ne pas renommer les chemins, mais d'indiquer comment il les renommerait. Supprimez cette option pour les renommer.