Vous allez avoir quelques problèmes si vous voulez renommer des fichiers et des répertoires en même temps. Renommer juste un fichier est assez facile. Mais vous voulez vous assurer que les répertoires sont également renommés. Vous ne pouvez pas simplement, mv Motörhead/Encöding Motorhead/Encoding
car Motorhead
il n’existera pas au moment de l’appel.
Nous avons donc besoin d’une traversée d’abord en profondeur de tous les fichiers et dossiers, puis de renommer le fichier ou le dossier actuel uniquement. Ce qui suit fonctionne avec GNU find
et Bash 4.2.42 sur mon OS X.
#!/usr/bin/env bash
find "$1" -depth -print0 | while IFS= read -r -d '' file; do
d="$( dirname "$file" )"
f="$( basename "$file" )"
new="${f//[^a-zA-Z0-9\/\._\-]/}"
if [ "$f" != "$new" ] # if equal, name is already clean, so leave alone
then
if [ -e "$d/$new" ]
then
echo "Notice: \"$new\" and \"$f\" both exist in "$d":"
ls -ld "$d/$new" "$d/$f"
else
echo mv "$file" "$d/$new" # remove "echo" to actually rename things
fi
fi
done
Vous pouvez changer l'expression régulière en utilisant new="${f//[\\\/\:\*\?\"<>|]/}"
si vous voulez remplacer tout ce que Windows ne peut pas gérer.
Enregistrez ce script sous rename.sh
, rendez-le exécutable avec chmod +x rename.sh
. Ensuite, appelez ça comme rename.sh /some/path
.
Assurez-vous de résoudre les conflits de noms de fichiers ( Notice
annonces « »).
Si vous êtes absolument certain que le remplacement est correct, supprimez-le echo
du script pour renommer des éléments au lieu d’imprimer le résultat.
Pour plus de sécurité, je vous conseillerais de commencer par tester ceci sur un petit sous-ensemble de fichiers.
Options expliquées
Pour expliquer ce qui se passe ici:
-depth
veillera à ce que les répertoires soient récursifs en profondeur d'abord, afin que nous puissions "tout remonter" à partir de la fin. Habituellement, find
traverse différemment (mais pas en largeur d'abord).
-print0
assure que la find
sortie est délimitée par des valeurs nulles, afin que nous puissions la lire read -d ''
dans la file
variable. Cela nous aide à gérer toutes sortes de noms de fichiers étranges, y compris ceux avec des espaces et même des nouvelles lignes.
- Nous allons obtenir le répertoire du fichier avec
dirname
. N'oubliez pas de toujours citer correctement vos variables, sinon tout chemin contenant des espaces ou des caractères globaux briserait ce script.
- Nous allons obtenir le nom du fichier (ou nom du répertoire) avec
basename
.
- Ensuite, nous retirons tout caractère non valide de l'
$f
utilisation des capacités de remplacement de chaîne de Bash. Invalide signifie tout ce qui n'est pas une lettre minuscule ou majuscule, un chiffre, une barre oblique ( \/
), un point ( \.
), un trait de soulignement ou un tiret moins.
- Si
$f
est déjà propre (le nom nettoyé est identique au nom actuel), ignorez-le.
- S'il
$new
existe déjà dans le répertoire $d
(par exemple, vous avez des fichiers nommés resume
et résumé
dans le même répertoire), émettez un avertissement. Vous ne voulez pas le renommer, car sur certains systèmes, cela mv foo foo
pose un problème. Autrement,
- Nous avons finalement renommé le fichier (ou répertoire) d'origine en son nouveau nom.
Comme cela n'agit que sur la hiérarchie la plus profonde, le changement Motörhead/Encöding
de nom Motorhead/Encoding
se fait en deux étapes:
mv Motörhead/Encöding Motörhead/Encoding
mv Motörhead Motorhead
Cela garantit que tous les remplacements sont effectués dans le bon ordre.
Exemples de fichiers et test
Supposons quelques fichiers dans un dossier de base appelé test
:
test
test/Motörhead
test/Motörhead/anöther_file.mp3
test/Motörhead/Encöding
test/Randöm
test/Täst
test/Täst/Töst
test/with space
test/with-hyphen.txt
test/work
test/work/resume
test/work/résumé
test/work/schedule
Voici la sortie d'une exécution en mode débogage (avec le echo
devant de mv
), c'est-à-dire les commandes qui seraient appelées et les avertissements de collision:
mv test/Motörhead/anöther_file.mp3 test/Motörhead/another_file.mp3
mv test/Motörhead/Encöding test/Motörhead/Encoding
mv test/Motörhead test/Motorhead
mv test/Randöm test/Random
mv test/Täst/Töst test/Täst/Tost
mv test/Täst test/Tast
mv test/with space test/withspace
Notice: "resume" and "résumé" both exist in test/work:
-rw-r—r-- … … test/work/resume
-rw-r—r-- … … test/work/résumé
Notez l'absence de messages pour with-hyphen.txt
, schedule
et test
lui - même.
mv
existe déjà, ce qui peut arriver (1) si vous avez des fichiers déjà propres (résultantmv foo foo
), ou (2) si vous avez des fichiers du même nom sauf pour les caractères spéciaux (par exemple,mv Encöding Encoding
où vous avez déjà unEncoding
fichier en plus deEncöding
).Je sais que ce n'est pas exactement ce que vous vouliez, mais si vous connaissez le codage d'origine, vous pouvez peut-être utiliser
convmv
pour changer le codage en UTF-8, ce qui devrait résoudre la plupart des problèmes.Cela a fonctionné pour moi sur un dossier avec certains noms de fichiers polonais encodés de manière invalide:
Notez que cette commande ne renomme réellement rien; ajouter une
--notest
option pour vraiment renommer les fichiers.la source
convmv
option est incroyablement simple et parfaite. Pour OP, ayant une multitude de jeux de caractères potentiels, cela pourrait être fusionné avec l’autre réponse, car ilconvmv
semble savoir quand ou non il rencontre le bon format. En parcourant les jeux de caractères viaconvmv --list
, on les obtiendrait correctement codés.convmv -t utf8 --nfc -f iso-8859-1 --notest -r .
---nfc
C'était pour se conformer à Linux avant OS X ou autre, taper simplementconvmv
donne les options (utiles).Je sais, vous avez demandé à renommer.
Mais vous pouvez facilement éviter le problème en utilisant un logiciel comme MusicBrainz Picard .
Il est capable d'identifier la musique (empreintes audio), de télécharger toutes les données nécessaires (y compris les images de couverture, le cas échéant) à partir de la vaste base de données MusicBrainz et de déplacer les fichiers pour que votre collection s'adapte à tous les motifs de votre choix. Je l'utilise depuis des années et cela a toujours fonctionné parfaitement avec tout, de Cyrilic à l'Arabe; et bien sûr (du moins pour les scripts basés sur le latin), il peut également effectuer la conversion en ASCII.
Avec cette approche, peu importe la qualité de votre collection, tant que les fichiers sont lisibles et complets.
(Ai-je mentionné que c'était gratuit? Aussi bien dans la liberté d'expression que dans la bière gratuite? Le logiciel et la base de données ..?)
la source