我想以编程方式使用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
个列表中没有。
答案 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