GNU/Linux >> Tutoriels Linux >  >> Linux

Comment renommer en masse des fichiers avec un encodage invalide ou remplacer en masse des caractères encodés invalides ?

Je sais que ce n'est pas exactement ce que vous vouliez, mais si vous connaissez l'encodage d'origine, vous pouvez peut-être utiliser convmv pour changer l'encodage en UTF-8, ce qui devrait résoudre la plupart des problèmes.

Cela a fonctionné pour moi sur un dossier contenant des noms de fichiers polonais non valides :

convmv -f cp1250 -t utf8 -r .

Notez que cette commande ne renomme en fait rien; ajouter --notest option pour vraiment renommer les fichiers.


Vous allez rencontrer des problèmes si vous souhaitez renommer les fichiers et 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 depuis Motorhead n'existera pas au moment de l'appel.

Nous avons donc besoin d'un parcours en profondeur de tous les fichiers et dossiers, puis de renommer uniquement le fichier ou le dossier actuel. 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 la regex en utilisant new="${f//[\\\/\:\*\?\"<>|]/}" si vous souhaitez 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-le comme rename.sh /some/path .

Assurez-vous de résoudre toutes les collisions de noms de fichiers ("Notice " annonces).

Si vous êtes absolument sûr il fait les bons remplacements, supprimez le echo du script pour renommer les choses au lieu de simplement imprimer ce qu'il fait.

Pour plus de sécurité, je vous recommande de tester d'abord ceci sur un petit sous-ensemble de fichiers.

Options expliquées

Pour expliquer ce qui se passe ici :

  • -depth garantira que les répertoires sont récursifs en profondeur d'abord, afin que nous puissions tout "rouler" à partir de la fin. Habituellement, find traverse différemment (mais pas en largeur d'abord).
  • -print0 assure le find la sortie est délimitée par null, nous pouvons donc la lire avec read -d '' dans le file variable. Cela nous aide à gérer toutes sortes de noms de fichiers étranges, y compris ceux avec des espaces et même des retours à la ligne.
  • Nous obtiendrons le répertoire du fichier avec dirname . N'oubliez pas de toujours mettre vos variables entre guillemets correctement, sinon tout chemin avec des espaces ou des caractères globaux casserait ce script.
  • Nous obtiendrons le nom de fichier réel (ou nom de répertoire) avec basename .
  • Ensuite, nous supprimons tout caractère invalide de $f en utilisant les 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 trait d'union moins.
  • Si $f est déjà propre (le nom nettoyé est identique au nom actuel), ignorez-le.
  • Si $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), émettre un avertissement. Vous ne voulez pas le renommer, car, sur certains systèmes, mv foo foo cause un problème. Sinon,
  • Nous renommons enfin le fichier (ou le répertoire) d'origine avec son nouveau nom

Comme cela n'agira que sur la hiérarchie la plus profonde, renommer Motörhead/Encöding à Motorhead/Encoding se fait en deux étapes :

  1. mv Motörhead/Encöding Motörhead/Encoding
  2. mv Motörhead Motorhead

Cela garantit que tous les remplacements sont effectués dans le bon ordre.

Exemples de fichiers et test d'exécution

Supposons que certains fichiers se trouvent 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 le 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é

Remarquez l'absence de messages pour with-hyphen.txt , schedule , et test lui-même.


Linux
  1. Comment chiffrer des fichiers avec gocryptfs sous Linux

  2. Comment convertir des fichiers en codage UTF-8 sous Linux

  3. Comment renommer des fichiers sous Linux

  4. Comment renommer des fichiers avec des espaces à l'aide du shell Linux ?

  5. Comment remplacer récursivement les caractères par sed ?

Comment renommer un ou plusieurs fichiers sous Linux

Comment synchroniser des fichiers avec Unison sous Linux

Comment supprimer des fichiers avec une extension spécifique sous Linux

Comment rechercher des fichiers avec la commande fd sous Linux

Comment télécharger des fichiers avec FileZilla

Comment renommer tous les fichiers avec des caractères spéciaux et des espaces dans un répertoire ?