Regex pour remplacer les caractères que Windows n'accepte pas dans un nom de fichier

J'essaie de construire une expression régulière qui détectera tout caractère que Windows n'accepte pas dans le cadre d'un nom de fichier (sont-ils les mêmes pour les autres OS? Je ne sais pas, pour être honnête).

Ces symboles sont:

  / : * ? "  | 

, de toute façon, c'est ce que j'ai: [\/:*?"<>|]

Le testeur sur http://gskinner.com/RegExr / montre que cela fonctionne. Pour la chaîne Allo*ha, le symbole * s'allume, signalant qu'il a été trouvé. Dois-je entrer Allo**ha cependant, seul le premier *] s'allume. Donc, je pense que je dois modifier cette regex pour trouver toutes les apparences des caractères mentionnés, mais je ne suis pas sûr.

Vous voyez, en Java, j'ai la chance d'avoir la fonction String.replaceAll (chaîne regex, remplacement de chaîne) . La description dit:

Remplace chaque sous-chaîne de cette chaîne qui correspond à l'expression régulière donnée par le remplacement donné.

Donc, en d'autres termes, même si l'expression rationnelle ne trouve que le premier et puis arrête la recherche, cette fonction les trouvera toujours tous.

Par exemple: String.replaceAll("[\/:*?"<>|]","")

Cependant, je ne me sens pas capable de prendre ce risque. Quelqu'un sait comment je peux prolonger ça?

30
demandé sur Svante 2009-04-16 04:23:25

11 réponses

Les règles de nom de fichier Windows sont difficiles . Vous ne faites que gratter la surface.

Par exemple, voici certaines choses qui ne sont pas des noms de fichiers valides, en plus des chracters que vous avez énumérés:

                                    (yes, that's an empty string)
.
.a
a.
 a                                  (that's a leading space)
a                                   (or a trailing space)
com
prn.txt
[anything over 240 characters]
[any control characters]
[any non-ASCII chracters that don't fit in the system codepage,
 if the filesystem is FAT32]

Suppression des caractères spéciaux dans une seule chaîne de type regex sub.replaceAll () ne suffit pas; vous pouvez facilement vous retrouver avec quelque chose d'invalide comme une chaîne vide ou une fin ‘.’ ou‘. Remplacer quelque chose comme " [^A-Za-z0-9_.] * "avec' _ ' serait une meilleure première étape. Mais vous toujours besoin d'un traitement de plus haut niveau sur n'importe quelle plate-forme que vous utilisez.

14
répondu bobince 2009-04-16 01:54:09

Comme aucune réponse n'était assez bonne, je l'ai fait moi-même. j'espère que cela aide ;)

public static boolean validateFileName(String fileName) {
    return fileName.matches("^[^.\\\\/:*?\"<>|]?[^\\\\/:*?\"<>|]*") 
    && getValidFileName(fileName).length()>0;
}

public static String getValidFileName(String fileName) {
    String newFileName = fileName.replace("^\\.+", "").replaceAll("[\\\\/:*?\"<>|]", "");
    if(newFileName.length()==0)
        throw new IllegalStateException(
                "File Name " + fileName + " results in a empty fileName!");
    return newFileName;
}
16
répondu Alex_M 2018-05-10 00:34:11

Pour mémoire, les systèmes compatibles POSIX (y compris UNIX et Linux) prennent en charge tous les caractères sauf le caractère nul ('\0') et la barre oblique ('/') dans les noms de fichiers. Les caractères spéciaux tels que l'espace et l'astérisque doivent être échappés sur la ligne de commande afin qu'ils ne prennent pas leurs rôles habituels.

2
répondu Artelius 2009-04-16 00:37:06

J'utilise une expression régulière pure et simple. Je donne des caractères qui peuvent se produire et par la négation de "^" je change tous les autres en signe de tels. "_"

Chaîne fileName = someString.replaceAll ("[^A-zA-Z0-9\\.\\-]", "_");

Par exemple: Si vous ne voulez pas être dans l'expression "."puis retirez le"\\."

Chaîne fileName = someString.replaceAll ("[^A-zA-Z0-9\\-]", "_");

2
répondu Adam111p 2017-09-15 07:32:30

Java a une fonction replaceAll, mais chaque langage de programmation a un moyen de faire quelque chose de similaire. Perl, par exemple, utilise le commutateur g pour signifier un remplacement global. La fonction sub de Python vous permet de spécifier le nombre de remplacements à effectuer. Si, pour une raison quelconque, votre langue n'avait pas d'équivalent, Vous pouvez toujours faire quelque chose comme ceci:

while (filename.matches(bad_characters)
  filename.replace(bad_characters, "")
1
répondu Pesto 2009-04-16 00:38:35

J'extrait tous les caractères de mot et les caractères d'espace de la chaîne d'origine et je m'assure également que le caractère d'espace n'est pas présent à la fin de la chaîne. Voici mon extrait de code en java.

temp_string = original.replaceAll("[^\\w|\\s]", "");
final_string = temp_string.replaceAll("\\s$", "");

Je pense que j'ai aidé quelqu'un.

1
répondu Vysakh Prem 2013-07-11 11:57:42

Vous pouvez essayer d'autoriser uniquement les éléments que vous souhaitez que l'utilisateur puisse entrer, par exemple A-Z, A-z et 0-9.

0
répondu Kredns 2009-04-16 00:30:24

Vous ne pouvez pas le faire avec une seule expression rationnelle, car une expression rationnelle correspond toujours à une sous-chaîne si l'entrée. Considérez le mot Alo*h*a, Il n'y a pas de sous-chaîne qui contient tous les *s, et pas n'importe quel autre caractère. Donc, si vous pouvez utiliser la fonction replaceAll, restez avec elle.

BTW, l'ensemble des caractères interdits est différent dans d'autres systèmes d'exploitation.

0
répondu jpalecek 2009-04-16 00:38:14

J'en ai fait un très Méthode simple cela fonctionne pour moi pour la plupart des cas courants:

// replace special characters that windows doesn't accept
private String replaceSpecialCharacters(String string) {
    return string.replaceAll("[\\*/\\\\!\\|:?<>]", "_")
            .replaceAll("(%22)", "_");
}

%22 est codé si vous avez qoute (") dans les noms de fichier.

0
répondu Ivan Aracki 2016-11-08 13:53:41

La regex / syntaxe requise (JS):

.trim().replace(/[\\/:*?\"<>|]/g,"").substring(0,240);

Lorsque le dernier bit est facultatif, utilisez uniquement lorsque vous souhaitez limiter la longueur à 240.

Autres fonctions utiles (JS):

.toUppperCase();
.toLowerCase();
.replace(/  /g,' ');     //normalising multiple spaces to one, add before substring.
.includes("str");        //check if a string segment is included in the filename
.split(".").slice(-1);   //get extension, given the entire filename contains a .
0
répondu Chiu Chun Sun 2018-01-28 15:27:46

Windows n'accepte pas non plus " % " comme nom de fichier.

Si vous construisez une expression générale qui peut affecter les fichiers qui seront éventuellement déplacés vers un autre système d'exploitation, je vous suggère de mettre plus de caractères qui peuvent avoir des problèmes avec eux.

Par exemple, sous Linux (beaucoup de distributions que je connais), certains utilisateurs peuvent avoir des problèmes avec les fichiers contenant [b]& ! ] [ / - ( )[/b]. Les symboles sont autorisés dans les noms de fichiers, mais ils peuvent avoir besoin d'être spécialement traitée par les utilisateurs et certains les programmes ont des bugs causés par leur existence.

-1
répondu Balaco 2015-10-16 14:24:46