我知道/在Linux中是非法的,下面这些在Windows中是非法的 (我认为)*。" / \ []:;|,

我还遗漏了什么?

然而,我需要一份全面的指南,一份考虑到各种因素的指南 双字节字符。链接到外部资源对我来说很好。

我需要首先在文件系统上创建一个目录,其名称可能是 包含禁用字符,所以我计划将这些字符替换为 下划线。然后,我需要将这个目录及其内容写入一个zip文件 (使用Java),因此关于zip目录名称的任何其他建议 不胜感激。


当前回答

对于Windows,您可以使用PowerShell检查它

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

要显示您可以转换的UTF-8代码

$enc = [system.Text.Encoding]::UTF8
$PathInvalidChars | foreach { $enc.GetBytes($_) }

$FileNameInvalidChars = [System.IO.Path]::GetInvalidFileNameChars() #41 chars

$FileOnlyInvalidChars = @(':', '*', '?', '\', '/') #5 chars - as a difference

其他回答

对于任何寻找正则表达式的人:

const BLACKLIST = /[<>:"\/\\|?*]/g;

虽然唯一非法的Unix字符可能是/和NULL,但应该考虑到命令行解释。

例如,虽然在Unix中将文件命名为1>&2或2>&1是合法的,但在命令行中使用这样的文件名可能会被误解。

类似地,也可以将文件命名为$PATH,但当试图从命令行访问它时,shell将把$PATH转换为其变量值。

要让Windows告诉你答案,最简单的方法是尝试通过资源管理器重命名文件,并输入反斜杠/作为新名称。Windows会弹出一个消息框,告诉你非法字符的列表。

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

微软文档-命名文件,路径和命名空间-命名约定

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) 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. 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). Other rules Windows: Filenames cannot end in a space or dot. macOS: You didn't ask for it, but just in case: Colon : and forward slash / depending on context are not permitted (e.g. Finder supports slashes, terminal supports colons). (More details)

下面是一个基于Christopher Oezbek的答案的windows c#实现

containsFolder布尔值使它更加复杂,但希望涵盖所有内容

/// <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();
}