Quels caractères sont interdits dans les noms de répertoires Windows et Linux?

Je sais que / est illégal sous Linux, et ce qui suit est illégal sous Windows (je pense) * . " / \ [ ] ; | = ,

Qu’est-ce qu’il me manque d’autre?

J’ai besoin d’un guide complet, cependant, qui prenne en compte les caractères à deux octets. Le lien avec des ressources extérieures me convient parfaitement.

Je dois d’abord créer un répertoire sur le système de fichiers en utilisant un nom pouvant contenir des caractères interdits, je prévois donc de remplacer ces caractères par des traits de soulignement. J’ai ensuite besoin d’écrire ce répertoire et son contenu dans un fichier zip (en utilisant Java), donc tout conseil supplémentaire concernant les noms des répertoires zip serait apprécié.

Un “guide complet” des noms de fichiers interdits ne fonctionnera pas sous Windows car il réserve les noms de fichiers ainsi que les caractères. Oui, des caractères comme * " ? Et autres sont interdits, mais il existe un nombre infini de noms composés uniquement de caractères valides interdits. Par exemple, les espaces et les points sont des noms de fichiers valides, mais les noms composés uniquement de ces caractères sont interdits.

Windows ne fait pas la distinction entre majuscules et minuscules. Vous ne pouvez donc pas créer un dossier nommé A s’il en existe déjà a . Pire encore, les noms apparemment autorisés comme PRN et CON , et bien d’autres, sont réservés et ne sont pas autorisés. Windows a également plusieurs ressortingctions de longueur; Un nom de fichier valide dans un dossier peut ne plus être valide s’il est déplacé dans un autre dossier. Les règles pour nommer les fichiers et les dossiers sont sur MSDN.

Vous ne pouvez pas, en général, utiliser du texte généré par l’utilisateur pour créer des noms de répertoire Windows. Si vous souhaitez autoriser les utilisateurs à nommer tout ce qu’ils veulent, vous devez créer des noms sécurisés comme A , AB , A2 et autres, stocker les noms générés par l’utilisateur et leurs équivalents de chemin dans un fichier de données d’application et effectuer un mappage de chemin dans votre application .

Si vous devez absolument autoriser les noms de dossiers générés par l’utilisateur, la seule façon de savoir s’ils sont invalides est de détecter les exceptions et de supposer que le nom est invalide. Même cela est périlleux, car les exceptions levées pour l’access refusé, les lecteurs hors ligne et les espaces hors disque se chevauchent avec ceux qui peuvent être lancés pour des noms non valides. Vous ouvrez une énorme boîte de mal.

Gardons les choses simples et répondons à la question en premier.

  1. Les caractères ASCII imprimables interdits sont:

    • Linux / Unix:

       / (forward slash) 
    • Les fenêtres:

       < (less than) > (greater than) : (colon - sometimes works, but is actually NTFS Alternate Data Streams) " (double quote) / (forward slash) \ (backslash) | (vertical bar or pipe) ? (question mark) * (asterisk) 
  2. Caractères non imprimables

    Si vos données proviennent d’une source qui autoriserait des caractères non imprimables, il y a plus à vérifier.

    • Linux / Unix:

       0 (NULL byte) 
    • Les fenêtres:

       0-31 (ASCII control characters) 

    Remarque: Bien qu’il soit légal sous les systèmes de fichiers Linux / Unix de créer des fichiers avec des caractères de contrôle dans le nom du fichier, cela peut être un cauchemar pour les utilisateurs de gérer de tels fichiers .

  3. Noms de fichiers réservés

    Les noms de fichiers suivants sont réservés:

    • Les fenêtres:

       CON, PRN, AUX, NUL COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9 LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9 
  4. Autres règles

    • Les fenêtres:

      Les noms de fichiers ne peuvent pas se terminer par un espace ou un point.

Sous Linux et d’autres systèmes liés à Unix, il n’y a que deux caractères qui ne peuvent pas apparaître dans le nom d’un fichier ou d’un répertoire, à savoir NUL '\0' et slash '/' . La barre oblique, bien sûr, peut apparaître dans un nom de chemin, en séparant les composants de répertoire.

La rumeur 1 dit que Steven Bourne (de la renommée «shell») avait un répertoire contenant 254 fichiers, un pour chaque lettre (code de caractère) pouvant apparaître dans un nom de fichier (sauf / , '\0' ; le nom était . le répertoire actuel, bien sûr). Il a été utilisé pour tester le shell Bourne et perturber régulièrement les programmes imprudents tels que les programmes de sauvegarde.

D’autres personnes ont couvert les règles Windows.

Notez que MacOS X a un système de fichiers insensible à la casse.


1 Ce fut Kernighan & Pike dans The Practice of Programming qui en dit autant au chapitre 6, Testing, §6.5 Stress Tests:

Lorsque Steve Bourne écrivait son shell Unix (connu sous le nom de shell Bourne), il a créé un répertoire de 254 fichiers avec des noms à un caractère, un pour chaque valeur d’octet sauf '\0' et une barre oblique, les deux caractères ne peut pas apparaître dans les noms de fichiers Unix. Il a utilisé ce répertoire pour toutes sortes de tests de correspondance de modèles et de marquage. (Le répertoire de test a bien sûr été créé par un programme.) Pendant des années, ce répertoire était le fléau des programmes de recherche de fichiers. il les a testés à la destruction.

Au lieu de créer une liste noire de caractères, vous pouvez utiliser une liste blanche . Tout bien considéré, la gamme de caractères qui a du sens dans un contexte de nom de fichier ou de répertoire est assez courte, et à moins que vous ayez des exigences de nommage très spécifiques, vos utilisateurs ne le conserveront pas s’ils ne peuvent pas utiliser la table ASCII entière.

Il ne résout pas le problème des noms réservés dans le système de fichiers cible, mais avec une liste blanche, il est plus facile d’atténuer les risques à la source.

Dans cet esprit, il s’agit d’une série de caractères pouvant être considérés comme sûrs:

  • Lettres (az AZ) – Caractères Unicode également, si nécessaire
  • Chiffres (0-9)
  • Souligner (_)
  • Trait d’union (-)
  • Espace
  • Dot (.)

Et tout caractère sécurisé supplémentaire que vous souhaitez autoriser. Au-delà, vous devez simplement appliquer des règles supplémentaires concernant les espaces et les points . Ceci est généralement suffisant:

  • Le nom doit contenir au moins une lettre ou un chiffre (pour éviter uniquement les points / espaces)
  • Le nom doit commencer par une lettre ou un chiffre (pour éviter les points / espaces en tête)

Cela permet déjà des noms assez complexes et absurdes. Par exemple, ces noms seraient possibles avec ces règles et constitueraient des noms de fichiers valides sous Windows / Linux:

  • A...........ext
  • B -.- .ext

Essentiellement, même avec si peu de personnages en liste blanche, vous devez toujours décider de ce qui est réellement logique et valider / ajuster le nom en conséquence. Dans l’une de mes applications, j’ai utilisé les mêmes règles que ci-dessus, mais j’ai supprimé tous les points et espaces en double.

Eh bien, si ce n’est que pour des raisons de recherche, votre meilleur pari est de regarder cette entrée Wikipedia sur les noms de fichiers .

Si vous voulez écrire une fonction portable pour valider les entrées utilisateur et créer des noms de fichiers en fonction de cela, la réponse courte est « ne pas le faire» . Jetez un coup d’oeil à un module portable comme Perl ‘s File :: Spec pour avoir un aperçu de tous les sauts nécessaires pour accomplir une telle tâche “simple”.

Le moyen le plus simple pour que Windows vous réponde est d’essayer de renommer un fichier via Explorer et de taper / pour le nouveau nom. Windows affichera une boîte de message vous indiquant la liste des caractères illégaux.

 A filename cannot contain any of the following characters: \ / : * ? " < > | 

https://support.microsoft.com/en-us/kb/177506

Pour Windows, vous pouvez le vérifier avec PowerShell

 $PathInvalidChars = [System.IO.Path]::GetInvalidPathChars() #36 chars 

Pour afficher les codes UTF-8 que vous pouvez convertir

 $enc = [system.Text.Encoding]::UTF8 $PathInvalidChars | foreach { $enc.GetBytes($_) } $FileNameInvalidChars = [System.IO.Path]::GetInvalidFileNameChars() #41 chars $FileOnlyInvalidChars = @(':', '*', '?', '\', '/') #5 chars - as a difference 

Au 18/04/2017, aucune liste simple noire ou blanche de caractères et de noms de fichiers n’est évidente parmi les réponses à ce sujet – et il y a beaucoup de réponses.

La meilleure suggestion que je pouvais proposer était de laisser l’utilisateur nommer le fichier comme il l’aime. En utilisant un gestionnaire d’erreurs lorsque l’application tente d’enregistrer le fichier, prenez des exceptions, supposez que le nom du fichier est à blâmer (évidemment après vous être assuré que le chemin de sauvegarde était correct) et demandez à l’utilisateur un nouveau nom de fichier. Pour de meilleurs résultats, placez cette procédure de vérification dans une boucle qui se poursuit jusqu’à ce que l’utilisateur le trouve correctement ou abandonne. Travaillé le mieux pour moi (au moins en VBA).

Exemple de code VBA: (sera ajouté plus tard aujourd’hui)

Bien que les seuls caractères Unix illégaux puissent être / et NULL , une certaine considération pour l’interprétation de la ligne de commande devrait être incluse.

Par exemple, s’il peut être légal de nommer un fichier 1>&2 ou 2>&1 sous Unix, les noms de fichiers tels que celui-ci peuvent être mal interprétés lorsqu’ils sont utilisés sur une ligne de commande.

De même, il est possible de nommer un fichier $PATH , mais lorsque vous tentez d’y accéder depuis la ligne de commande, le shell $PATH en sa valeur de variable.

Lorsque vous créez des raccourcis Internet sous Windows, pour créer le nom du fichier, il ignore les caractères illégaux, à l’exception de la barre oblique, qui est convertie en minus.

Dans les shells Unix, vous pouvez citer presque tous les caractères entre guillemets simples. Sauf la citation unique elle-même, et vous ne pouvez pas exprimer les caractères de contrôle, car \ n’est pas développé. Il est possible d’accéder à la citation elle-même à partir d’une chaîne entre guillemets, car vous pouvez concaténer des chaînes avec des guillemets simples et doubles, comme 'I'"'"'m' qui peut être utilisé pour accéder à un fichier appelé "I'm" citation aussi possible ici).

Vous devez donc éviter tous les caractères de contrôle, car ils sont trop difficiles à saisir dans le shell. Le rest est amusant, en particulier les fichiers commençant par un tiret, car la plupart des commandes lisent ces options comme options, sauf si vous avez deux tirets -- avant ou si vous les spécifiez avec ./ , ce qui masque également le démarrage - .

Si vous voulez être gentil, n’utilisez aucun des caractères que le shell et les commandes typiques utilisent comme éléments syntaxiques, parfois dépendants de la position, par exemple, vous pouvez toujours utiliser - , mais pas comme premier caractère; même avec . , vous pouvez l’utiliser comme premier caractère uniquement lorsque vous le voulez (“fichier caché”). Lorsque vous êtes méchant, vos noms de fichiers sont des séquences d’échappement VT100 ;-), de sorte qu’un ls scanne la sortie.

J’avais le même besoin et recherchais des recommandations ou des références standard et je suis tombé sur ce sujet. Ma liste noire de caractères à éviter dans les noms de fichiers et de répertoires est la suivante:

 $CharactersInvalidForFileName = { "pound" -> "#", "left angle bracket" -> "<", "dollar sign" -> "$", "plus sign" -> "+", "percent" -> "%", "right angle bracket" -> ">", "exclamation point" -> "!", "backtick" -> "`", "ampersand" -> "&", "asterisk" -> "*", "single quotes" -> "“", "pipe" -> "|", "left bracket" -> "{", "question mark" -> "?", "double quotes" -> "”", "equal sign" -> "=", "right bracket" -> "}", "forward slash" -> "/", "colon" -> ":", "back slash" -> "\\", "lank spaces" -> "b", "at sign" -> "@" };