Comment supprimer les caractères non valides des noms de fichiers?

47

J'ai des fichiers avec des caractères non valides comme ceux-ci

009_-_�%86ndringshåndtering.html

C'est un Æcas où quelque chose s'est mal passé dans le nom du fichier.

Est-il possible de supprimer tous les caractères non valides?

ou pourrait trêtre utilisé en quelque sorte?

echo "009_-_�%86ndringshåndtering.html" | tr ???
Sandra
la source
5
Les caractères ne sont probablement pas "invalides", sinon le système de fichiers ne les stockerait pas (à moins que vous n'ayez fait quelque chose de vraiment désagréable pour le système de fichiers ). Avez-vous essayé de changer vos paramètres régionaux (par exemple en UTF8) pour afficher les noms correctement?
James O'Gorman

Réponses:

41

Une façon serait avec sed:

mv 'file' $(echo 'file' | sed -e 's/[^A-Za-z0-9._-]/_/g')

Remplacez filepar votre nom de fichier, bien sûr. Ceci remplacera tout ce qui n'est pas une lettre, un chiffre, un point, un trait de soulignement ou un tiret avec un trait de soulignement. Vous pouvez ajouter ou supprimer des caractères pour les conserver à votre guise et / ou remplacer le caractère de remplacement par un autre élément ou rien du tout.

James Sneeringer
la source
4
J'ai utilisé:f='file'; mv 'file' ${f//[^A-Za-z0-9._-]/_}
Louis
1
Recherchez la meilleure solution de H. Hess ci-dessous ... (et mon commentaire amusant à côté de :))
Jan Sila
31

Je suppose que vous êtes sur une machine Linux et que les fichiers ont été créés sur une machine Windows. Linux utilise UTF-8 comme codage de caractères pour les noms de fichiers, tandis que Windows utilise autre chose. Je pense que c'est la cause du problème.

Je voudrais utiliser "convmv". C'est un outil qui peut convertir les noms de fichiers d'un encodage de caractères en un autre. Pour l’Europe occidentale, l’un de ces programmes fonctionne normalement:

convmv -r -f windows-1252 -t UTF-8 .
convmv -r -f ISO-8859-1 -t UTF-8 .
convmv -r -f cp-850 -t UTF-8 .

Si vous avez besoin de l’installer sur un Linux basé sur Debian, vous pouvez le faire en lançant:

sudo apt-get install convmv

Cela fonctionne pour moi à chaque fois et il récupère le nom de fichier d'origine.

Source: LeaseWebLabs

Mevdschee
la source
1
cela semble prometteur, mais avez-vous une idée de la manière dont l'encodage est défini? J'ai un répertoire appelé Save the current file in Word 97-2004 format\sco.workflowqui a été créé sur mon Mac (via Microsoft Office) et les encodages ci-dessus n'ont aucun effet.
Sridhar Sarnobat
Il est intéressant de noter que par défaut, convmv s'exécute en mode "test", où il effectue simplement une analyse à blanc et vous indique les fichiers à déplacer. Il vous dira ensuite de le réexécuter avec l' --notestoption de renommer les fichiers.
Kenny Rasschaert
16

Je suppose que vous voulez dire que vous voulez traverser le système de fichiers et réparer tous ces fichiers?

Voici comment je le ferais

find /path/to/files -type f -print0 | \
perl -n0e '$new = $_; if($new =~ s/[^[:ascii:]]/_/g) {
  print("Renaming $_ to $new\n"); rename($_, $new);
}'

Tous les fichiers contenant des caractères non ASCII seraient remplacés par des caractères de soulignement ( _). Attention, si un fichier portant le nouveau nom existe déjà, il sera écrasé. Le script peut être modifié pour vérifier si tel est le cas, mais je ne l'ai pas intégré pour que cela reste simple.

Patrick
la source
13

Après les réponses sur https://stackoverflow.com/questions/2124010/grep-regex-to-match-non-ascii-characters , vous pouvez utiliser:

rename 's/[^\x00-\x7F]//g' *

*correspond aux fichiers que vous souhaitez renommer. Si vous voulez le faire sur plusieurs annuaires, vous pouvez faire quelque chose comme:

find . -exec rename 's/[^\x00-\x7F]//g' "{}" \;

Vous pouvez utiliser l'argument -n renamepour effectuer un essai, et voir ce qui serait changé, sans le changer.

rien101
la source
Est-il possible de modifier cela pour conserver des caractères étrangers tels que ü et ä par exemple?
Elder Geek
Seul le second a fonctionné pour moi. Tout était dans le même répertoire, donc je ne suis pas sûr de la différence…?
Shautieh
1
@Shautieh: le -n l'arrête de fonctionner. Je vais clarifier la réponse.
naught101
renommer peut être lent lorsqu'il s'agit de traiter beaucoup de fichiers. Si vous souhaitez accélérer le processus, cochez la case Rechercher. Je ne sais pas comment faire cela cependant.
Isaaclw
13

Certains fichiers japonais contenant des noms de fichiers endommagés ont été récupérés à partir d’une clé USB endommagée et les solutions ci-dessus ne fonctionnent pas.

Je recommande le forfait de désintoxication:

L'utilitaire de désintoxication renomme les fichiers pour faciliter leur travail. Il supprime les espaces et autres inconvénients de ce type. Il va également traduire ou nettoyer les caractères Latin-1 (ISO 8859-1) codés en ASCII 8 bits, les caractères Unicode codés en UTF-8 et les caractères d'échappement CGI.

Exemple d'utilisation:

detox -r -v /path/to/your/files
-r Recurse dans des sous-répertoires
-v Soyez précis sur les fichiers en cours de changement de nom 
-n Peut être utilisé pour un essai à sec (ne montrer que ce qui serait changé)
H. Hess
la source
2
Cela devrait être beaucoup plus élevé, j'invite tout le monde à regarder detoxavant de réinventer la roue. Si vous consultez la page de manuel, vous constaterez qu’elle couvre toutes les autres solutions proposées ici en raison de sa flexibilité.
emk2203
Ezekiel 25:17 - Béni soit celui qui, au nom de la charité et du bien, vote favorablement cette solution, car il est vraiment le gardien de son frère et le découvreur des enfants perdus.
Jan Sila
De manière non intuitive, le chemin ne peut pas être '.' dans debian. Si vous utilisez un '.' il ne trouve rien.
Isaaclw
Je me demande si cela fonctionne vraiment, il semble supprimer / remplacer les caractères chinois, par exemple 的节奏啊, mais ces caractères sont un nom de fichier valide.
mardi
5

Ce script shell assainit un répertoire de manière récursive pour rendre les fichiers portables entre Linux / Windows et FAT / NTFS / exFAT. Il supprime les caractères de contrôle /:*?"<>\|et certains noms Windows réservés tels que COM0.

sanitize() {
  shopt -s extglob;

  filename=$(basename "$1")
  directory=$(dirname "$1")

  filename_clean=$(echo "$filename" | sed -e 's/[\\/:\*\?"<>\|\x01-\x1F\x7F]//g' -e 's/^\(nul\|prn\|con\|lpt[0-9]\|com[0-9]\|aux\)\(\.\|$\)//i' -e 's/^\.*$//' -e 's/^$/NONAME/')

  if (test "$filename" != "$filename_clean")
  then
    mv -v "$1" "$directory/$filename_clean"
  fi
}

export -f sanitize

sanitize_dir() {
  find "$1" -depth -exec bash -c 'sanitize "$0"' {} \;
}

sanitize_dir '/path/to/somewhere'

Linux est en théorie moins restrictif ( /et \0est strictement interdit dans les noms de fichiers), mais dans la pratique, plusieurs caractères interfèrent avec les commandes bash (comme *...), ils doivent donc également être évités dans les noms de fichiers.

Excellentes sources pour les restrictions de nommage des fichiers:

KrisWebDev
la source
1
C'est ce que je recherche! mais ajoutez des guillemets pour prendre en charge les répertoires contenant des espaces, recherchez "$ 1" -depth -exec bash -c 'désinfecter "$ 0"' {} \;
mmv-ru
1

Si vous souhaitez gérer les sauts de ligne, les caractères multi-octets, les espaces, les tirets, les barres obliques inverses et les espaces, vous aurez besoin de quelque chose de plus robuste, consultez la réponse suivante:
https://superuser.com/a/858671/365691

Je mets le script sur code.google.com si cela vous intéresse: rnf-bash-rename-script

A.Danischewski
la source
Le script lié ici a résolu le problème pour moi
Jeremiah Rose
0

J'utilise ce one-liner pour supprimer les caractères non valides dans les fichiers de sous-titres:

for f in *.srt; do nf=$(echo "$f" |sed -e 's/[^A-Za-z0-9.-]/./g;s/\.\.\././g;s/\.\././g'); test "$f" != "$nf" && mv "$f" "$nf" && echo "$nf"; done
  1. Ne traiter que les fichiers * .srt (* peut être utilisé à la place de * .srt pour traiter chaque fichier)
  2. Supprime tous les autres caractères sauf les lettres A-Za-z, les chiffres 0 à 9, les points "." Et les tirets "-".
  3. Supprime les doubles ou triples périodes possibles
  4. Vérifie si le nom du fichier doit être changé
  5. Si true, il renomme le fichier avec la commande mv, puis affiche les modifications apportées avec la commande echo

Cela fonctionne pour normaliser les noms de répertoire des films:

for f in */; do nf=$(echo "$f" |sed -e 's/[^A-Za-z0-9.]/./g' -e 's/\.\.\././g' -e 's/\.\././g' -e 's/\.*$//'); test "$f" != "$nf" && mv "$f" "$nf" && echo "$nf"; done

Mêmes étapes que ci-dessus mais j'ai ajouté une commande sed supplémentaire pour supprimer un point à la fin du répertoire.

X-Men Days of Future Past (2014) [1080p]
Modifié en:
X-Men.Days.of.Future.Past.2014.1080p

Brian Kuepper
la source
-2

pour le fichier en *; do mv "$ file" $ (echo "$ file" | sed -e '/ [^ A-Za-z0-9. -] / / g'); terminé &

Jairo Bernal
la source
2
Vous devriez expliquer ce que fait votre code et utiliser un formatage approprié. Votre code peut entraîner la suppression de fichiers en introduisant des collisions dans les noms. Et faire tourner tout ça en arrière-plan est un peu idiot.
Kasperd