如何以编程方式重命名包含非法字符的Windows文件夹?

时间:2017-12-11 05:25:53

标签: vba illegal-characters

我想以编程方式使用VBA重命名包含一个或多个非法Windows字符的Windows文件夹。 (文件夹树来自Mac / Linux环境)。

非法字符在Windows /文件资源管理器中显示为.,可以操作该文件夹。

我尝试过的方法失败包括使用FileSystem对象和VBA Name命令。

获取具有非法字符的文件夹的实际名称是个问题。

执行dir /X显示文件夹的短(8.3格式)名称,但全名出现在命令窗口中,?替换非法字符。

用这个名字提供?对于文件夹操作的各种例程(例如FileSystemObject GetFolder,VB Name函数,GetShortName)导致操作没有找到要操作的文件。

运行Dir /X > Foldernames.txt会生成一个显示?的ASCII文件?替换非法字符,但在二进制编辑器(Frhed)中检查文件显示完整文件夹名称中的非法字符的3个字节。这些是Chr(239)Chr(128)Chr(162)。使用此字符串替换非法char文件夹名称仍导致文件夹未找到行为。

使用文件夹名称中的实际非法值(Chr (149))也会导致找不到文件夹行为。

Dir /X输出中显示短文件名(8.3格式),可以通过此名称访问该文件夹。但是,我无法看到如何区分同一位置中具有不同非法字符的文件夹的短名称,并且仅在文件夹存在时才会生成短名称,因此除非我可以直接使用非法字符访问foldername,否则它没什么用处

占位符(UxFFFD)有一个unicode符号,在黑色钻石中显示为问号,我偶尔会看到但在Dir /X个列表中没有。

2 个答案:

答案 0 :(得分:0)

我建议通过批处理来完成这项工作。

通过列表获取文件的实际名称。

你可以使用这样的批次:

dir "F:\batchs" > "F:\batchs\list.txt"
exit

如果您发现该名称,请将其复制并替换"' inserthere '"在这段代码中:

ren '_inserthere_' newname.txt
exit

然后再次将其作为批处理作业运行。这可能会起到作用。

答案 1 :(得分:0)

我发现通过短(8.3)格式名称访问带有非法字符的文件和文件夹非常费力。从不存在的路径生成短名称是不可能的 - 因为生成短名称的算法显然会发生变化,我找不到它的逆向工程。

获取短名称的唯一方法是为具有非法字符的文件夹执行Dir / X列表,或者包含带有非法字符的文件名,并将其发送到文件,然后可以对其进行解析。文件中文件或文件夹的长名称有时包括非法字符(如果它是?,这是最常见的),因此可以搜索。用于处理文件夹的VBA代码如下。一旦找到具有非法字符的文件夹的短名称,就可以轻松地重命名该文件并将其作为ByRef参数返回。

' Procedure : LegalPath
' Author    : Simon
' Date      : 11/12/2017
' Purpose   : returns true if all path chars are legal and changes illegals to _ in sLegalPath if not

Public Function LegalPath(ByVal sPath As String, ByRef sLegalPath As String)            As Boolean

Dim iColon As Long
Dim J As Long
Dim sIllegalChars As String
Dim sOutPath As String
On Error GoTo LegalPath_Error

LegalPath = False
sIllegalChars = ""
'If InStr(sPath, "\") <> 0 Then Exit Function
If InStr(sPath, "/") <> 0 Then sIllegalChars = sIllegalChars + "/"

iColon = InStr(sPath, ":")    ' allow colon at loc 2
If iColon <> 0 And iColon <> 2 Then sIllegalChars = sIllegalChars + ":"
If InStr(sPath, "*") <> 0 Then sIllegalChars = sIllegalChars + "*"
If InStr(sPath, "?") <> 0 Then sIllegalChars = sIllegalChars + "?"
If InStr(sPath, "<") <> 0 Then sIllegalChars = sIllegalChars + "<"
If InStr(sPath, ">") <> 0 Then sIllegalChars = sIllegalChars + ">"
If InStr(sPath, "|") <> 0 Then sIllegalChars = sIllegalChars + "|"

' check for bullet code (149)
For J = 1 To Len(sPath)
    If (asc(Mid(sPath, J, 1)) = 149) Then
        sIllegalChars = sIllegalChars & Mid(sPath, J, 1)
    End If
Next J

If (sIllegalChars <> "") Then
    LegalPath = False
    ' replace with illegals with underscore
    sOutPath = sLegalPath
    For J = 1 To Len(sIllegalChars)
        sOutPath = Replace(sOutPath, Mid(sIllegalChars, J, 1), "_")
    Next J
    sLegalPath = sOutPath
    Dim sParentFolder As String
    sParentFolder = GetFolderFromPath(TruncateR(sPath))
    Call shell(GetDAFolder & "\ListDir.bat """ & sParentFolder & """ """ & GetDAFolder & "\ListDir.txt""")

    Dim a As TextStream
    Dim fs As New Scripting.FileSystemObject
    Set a = fs.OpenTextFile(GetDAFolder & "\ListDir.txt", ForReading, False)


    Dim sWindowsFolderName As String
    Dim sWindowsShortName As String
    Dim sLine As String
    sWindowsFolderName = GetFileFromPath(TruncateR(sPath))
    Do While a.AtEndOfStream <> True
        sLine = a.ReadLine
        If (Len(sLine) > 50) Then
            If (Mid(sLine, 50) = sWindowsFolderName) Then
                sWindowsShortName = Mid(sLine, 37, 8)
                Name sParentFolder & "\" & sWindowsShortName As sLegalPath
                Exit Function
            End If
        End If
    Loop

Else
    LegalPath = True

End If

End Function

对于具有非法名称的文件,方法非常相似。非法字符被_替换。请注意,Unicode字符不会被标记为非法。

Public Function IsIllegalFileCharIN(ByRef sFileName As String, ByVal sFolder As String) As Boolean

Dim sRegex As String
Dim objRegExp As New RegExp
Dim sOut As String

sRegex = "[<>:""/\\|?*„]+"

With objRegExp
    .Pattern = sRegex
    .IgnoreCase = True
    .Global = True
    IsIllegalFileCharIN = .test(sFileName)

End With


If (IsIllegalFileCharIN) Then

    Dim sLegalFileName As String
    With objRegExp
        .Pattern = sRegex
        .IgnoreCase = True
        .Global = True
        sLegalFileName = .Replace(sFileName, "_")
    End With

    ' find file short name


    Call shell(GetDAFolder & "\ListDir.bat """ & sFolder & """ """ & GetDAFolder & "\ListDir.txt""")

    Dim a As TextStream
    Dim fs As New Scripting.FileSystemObject
    Set a = fs.OpenTextFile(GetDAFolder & "\ListDir.txt", ForReading, False)

    Dim sWindowsFolderName As String
    Dim sWindowsShortName As String
    Dim sLine As String
    sWindowsFolderName = sFileName
    Do While a.AtEndOfStream <> True
        sLine = a.ReadLine
        If (Len(sLine) > 50) Then
            If (Mid(sLine, 50) = sWindowsFolderName) Then
                sWindowsShortName = Mid(sLine, 37, 12)
                Name sFolder & "\" & sWindowsShortName As sFolder & "\" & sLegalFileName
                sFileName = sLegalFileName
                Exit Function
            End If
        End If
    Loop

End If



On Error GoTo 0
End Function

GetDAFolder是一个专用文件夹。批处理文件ListDir.Bat包含    dir /X %1 >%2