What characters are forbidden in Windows and Linux directory names?

前端 未结 17 2532
北海茫月
北海茫月 2020-11-22 01:05

I know that / is illegal in Linux, and the following are illegal in Windows (I think) * . \" / \\ [

相关标签:
17条回答
  • 2020-11-22 02:02

    For anyone looking for a regex:

    const BLACKLIST = /[<>:"\/\\|?*]/g;
    
    0 讨论(0)
  • 2020-11-22 02:05

    Let's keep it simple and answer the question, first.

    1. The forbidden printable ASCII characters are:

      • Linux/Unix:

        / (forward slash)
        
      • Windows:

        < (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. Non-printable characters

      If your data comes from a source that would permit non-printable characters then there is more to check for.

      • Linux/Unix:

        0 (NULL byte)
        
      • Windows:

        0-31 (ASCII control characters)
        

      Note: While it is legal under Linux/Unix file systems to create files with control characters in the filename, it might be a nightmare for the users to deal with such files.

    3. Reserved file names

      The following filenames are reserved:

      • Windows:

        CON, PRN, AUX, NUL 
        COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9
        LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, LPT9
        

        (both on their own and with arbitrary file extensions, e.g. LPT1.txt).

    4. Other rules

      • Windows:

        Filenames cannot end in a space or dot.

    0 讨论(0)
  • 2020-11-22 02:06

    The .NET Framework System.IO provides the following functions for invalid file system characters:

    • Path.GetInvalidFileNameChars
    • Path.GetInvalidPathChars

    Those functions should return appropriate results depending on the platform the .NET runtime is running in.

    0 讨论(0)
  • 2020-11-22 02:08

    When creating internet shortcuts in Windows, to create the file name, it skips illegal characters, except for forward slash, which is converted to minus.

    0 讨论(0)
  • 2020-11-22 02:10

    Here's a c# implementation for windows based on Christopher Oezbek's answer

    It was made more complex by the containsFolder boolean, but hopefully covers everything

    /// <summary>
    /// This will replace invalid chars with underscores, there are also some reserved words that it adds underscore to
    /// </summary>
    /// <remarks>
    /// https://stackoverflow.com/questions/1976007/what-characters-are-forbidden-in-windows-and-linux-directory-names
    /// </remarks>
    /// <param name="containsFolder">Pass in true if filename represents a folder\file (passing true will allow slash)</param>
    public static string EscapeFilename_Windows(string filename, bool containsFolder = false)
    {
        StringBuilder builder = new StringBuilder(filename.Length + 12);
    
        int index = 0;
    
        // Allow colon if it's part of the drive letter
        if (containsFolder)
        {
            Match match = Regex.Match(filename, @"^\s*[A-Z]:\\", RegexOptions.IgnoreCase);
            if (match.Success)
            {
                builder.Append(match.Value);
                index = match.Length;
            }
        }
    
        // Character substitutions
        for (int cntr = index; cntr < filename.Length; cntr++)
        {
            char c = filename[cntr];
    
            switch (c)
            {
                case '\u0000':
                case '\u0001':
                case '\u0002':
                case '\u0003':
                case '\u0004':
                case '\u0005':
                case '\u0006':
                case '\u0007':
                case '\u0008':
                case '\u0009':
                case '\u000A':
                case '\u000B':
                case '\u000C':
                case '\u000D':
                case '\u000E':
                case '\u000F':
                case '\u0010':
                case '\u0011':
                case '\u0012':
                case '\u0013':
                case '\u0014':
                case '\u0015':
                case '\u0016':
                case '\u0017':
                case '\u0018':
                case '\u0019':
                case '\u001A':
                case '\u001B':
                case '\u001C':
                case '\u001D':
                case '\u001E':
                case '\u001F':
    
                case '<':
                case '>':
                case ':':
                case '"':
                case '/':
                case '|':
                case '?':
                case '*':
                    builder.Append('_');
                    break;
    
                case '\\':
                    builder.Append(containsFolder ? c : '_');
                    break;
    
                default:
                    builder.Append(c);
                    break;
            }
        }
    
        string built = builder.ToString();
    
        if (built == "")
        {
            return "_";
        }
    
        if (built.EndsWith(" ") || built.EndsWith("."))
        {
            built = built.Substring(0, built.Length - 1) + "_";
        }
    
        // These are reserved names, in either the folder or file name, but they are fine if following a dot
        // CON, PRN, AUX, NUL, COM0 .. COM9, LPT0 .. LPT9
        builder = new StringBuilder(built.Length + 12);
        index = 0;
        foreach (Match match in Regex.Matches(built, @"(^|\\)\s*(?<bad>CON|PRN|AUX|NUL|COM\d|LPT\d)\s*(\.|\\|$)", RegexOptions.IgnoreCase))
        {
            Group group = match.Groups["bad"];
            if (group.Index > index)
            {
                builder.Append(built.Substring(index, match.Index - index + 1));
            }
    
            builder.Append(group.Value);
            builder.Append("_");        // putting an underscore after this keyword is enough to make it acceptable
    
            index = group.Index + group.Length;
        }
    
        if (index == 0)
        {
            return built;
        }
    
        if (index < built.Length - 1)
        {
            builder.Append(built.Substring(index));
        }
    
        return builder.ToString();
    }
    
    0 讨论(0)
提交回复
热议问题