我多年来一直是stackoverflow.com的潜伏者(很棒的网站和用户),但从来没有必要提问。现在是时候了:-)让我开始吧:
操作系统:x64 Windows 8.0到Windows 10(15063.14)(问题已存在多年,但我还没有完全追求它,所以我们可以排除它特定于特定的Windows版本)
FS:NTFS
问题:在同一目录中有2个具有相同(长)名称的文件,我无法弄清楚这是怎么回事。每当我手动升级我的电子邮件客户端时,就会发生这种情况。它的主要.EXE文件(MailClient.exe)永远不会要求替换,如果将新的文件复制到同一目录。相反,它们都放在那里,具有完全相同的长名称。
该问题与特定目录无关,我可以将两个.EXE文件复制到NTFS驱动器上新创建的目录而不会出现问题(也没有“覆盖”问题)。
让我告诉你:
C:\temp\2>dir
Volume in drive C is SSD 840 Pro
Volume Serial Number is 0C6D-D489
Directory of C:\temp\2
13.04.2017 02:29 <DIR> .
13.04.2017 02:29 <DIR> ..
21.10.2016 17:10 24.742.760 MailClient.exe
27.12.2016 03:26 24.911.872 MailCliеnt.exe
2 File(s) 49.654.632 bytes
2 Dir(s) 78.503.038.976 bytes free
但是,如果执行dir / x,则会出现:
C:\temp\2>dir /x
Volume in drive C is SSD 840 Pro
Volume Serial Number is 0C6D-D489
Directory of C:\temp\2
13.04.2017 02:29 <DIR> .
13.04.2017 02:29 <DIR> ..
21.10.2016 17:10 24.742.760 MAILCL~2.EXE MailClient.exe
27.12.2016 03:26 24.911.872 MAILCL~1.EXE MailCliеnt.exe
2 File(s) 49.654.632 bytes
2 Dir(s) 78.503.038.976 bytes free
所以他们显然有一个不同的8.3名称,好的,但完全相同的长名称。这是另一个情况截图。这两个文件在Windows“属性”对话框中也显示相同的位置(右键单击)。不幸的是我不允许发布图像(似乎) - 只是尝试过。所以你必须接受我的话。
我无法弄清楚这是怎么可能的,这让我烦恼;)一旦我将两个文件重命名为例如1.exe,Windows就会开始告诉我在同一目录中已经存在具有该名称的文件。所以它显然与文件名有关,但它们完全相同,没有多余的空格,没有,你可以从DIR命令中看到。
我也尝试重命名它们并为两者手动重写了确切的措辞“MailCient.exe”,以确保字符完全相同,Windows仍然不会抱怨,它们都再次去那里同名的。但是,将它们重命名为“Mail.exe”和“Mail.exe”将不起作用,然后Windows表示已存在具有该名称的另一个文件。但是,将它们命名为“MailClient.exe”只是绝对没问题,Windows没有抱怨。
另一个有趣的事实是,如果我直接使用mailclient.exe,就会发生这种情况:
C:\temp\2>dir mailclient.exe
Volume in drive C is SSD 840 Pro
Volume Serial Number is 0C6D-D489
Directory of C:\temp\2
21.10.2016 17:10 24.742.760 MailClient.exe
1 File(s) 24.742.760 bytes
0 Dir(s) 78.501.998.592 bytes free
但是,如果寻找* .exe,就会发生这种情况:
C:\temp\2>dir *.exe
Volume in drive C is SSD 840 Pro
Volume Serial Number is 0C6D-D489
Directory of C:\temp\2
21.10.2016 17:10 24.742.760 MailClient.exe
27.12.2016 03:26 24.911.872 MailCliеnt.exe
2 File(s) 49.654.632 bytes
0 Dir(s) 78.501.990.400 bytes free
这也产生了有趣的结果:
C:\temp\2>ren mailclient.exe *.bak
C:\temp\2>dir
Volume in drive C is SSD 840 Pro
Volume Serial Number is 0C6D-D489
Directory of C:\temp\2
13.04.2017 02:50 <DIR> .
13.04.2017 02:50 <DIR> ..
21.10.2016 17:10 24.742.760 MailClient.bak
27.12.2016 03:26 24.911.872 MailCliеnt.exe
2 File(s) 49.654.632 bytes
2 Dir(s) 78.501.990.400 bytes free
然后回来:
C:\temp\2>ren mailclient.bak MailClient.exe
C:\temp\2>dir
Volume in drive C is SSD 840 Pro
Volume Serial Number is 0C6D-D489
Directory of C:\temp\2
13.04.2017 02:51 <DIR> .
13.04.2017 02:51 <DIR> ..
21.10.2016 17:10 24.742.760 MailClient.exe
27.12.2016 03:26 24.911.872 MailCliеnt.exe
2 File(s) 49.654.632 bytes
2 Dir(s) 78.501.982.208 bytes free
我还检查了文件的权限并取得了所有权,它什么都没改变。另外,我清除了NTFS日志,甚至是事务日志+运行chkdsk,它也没有显示任何错误。
关于这种神秘局面的任何想法?我错过了什么?
非常感谢:)
更新#1:
我刚试过这个:转到Windows资源管理器并通过截断它们的名称来重命名这两个文件。所以我首先将第一个“MailClient.exe”重命名为“MailClien.exe”,然后将“MailClient.exe”重命名为“MailClien.exe”。再一次,Windows没有消息它们具有相同的名称,它只是重命名都很好。然后我继续“MailClie.exe”。工作。 但是,当我尝试将两者重命名为“MailCli.exe”时,Windows抱怨并告诉我已经存在另一个具有该名称的文件。试图从那里重新命名为“MailClient.exe”也不起作用,仅适用于其中一个,因为Windows说(并且也是如此)已经存在具有该名称的文件。所以它似乎归结为“e”可能在两个文件名中都有另一个ANSI字符?但是,我不会知道另一个“e”,或者我错过了什么?
答案 0 :(得分:1)
Harry Johnston is right:其中一个文件名包含一个Unicode字符,其外观与ANSI字符相同。
阅读Naming Files, Paths, and Namespaces:
在较新的文件系统上,例如NTFS,exFAT,UDFS和FAT32,Windows 将长文件名存储在磁盘上 Unicode ,这意味着 原始长文件名始终保留。即使是这样也是如此 无论代码如何,长文件名都包含扩展字符 在磁盘读取或写入操作期间处于活动状态的页面。
使用以下PowerShell脚本43381802b.ps1
检测并显示非ANSI文件名(请参阅下面的不同调用):
param( [string[]]$Path = '.',
[switch]$Cpp, ### list any non-ANSI character in file names like a C++ literal
### i.e. a prefix \u followed by a four digit Unicode code point
[switch]$All ### list all files including pure ANSI-encoded file names
)
Set-StrictMode -Version latest
$strArr = Get-ChildItem -path $Path
$arrDiff = @()
for ($i=0; $i -lt $strArr.Count; $i++) {
$strDiff = 'ANSI'
$strName = ''
$auxName = $strArr[$i].Name
for ( $k=0; $k -lt $auxName.Length; $k++ ) {
if ( [int][char]$auxName[$k] -gt 255 ) {
$strDiff = 'UCS2'
$strName += '\u{0:X4}' -f [int][char]$auxName[$k]
} else {
$strName += $auxName[$k]
}
}
if ( $All.IsPresent -or $strDiff -eq 'UCS2' ) {
$strArr[$i] | Add-Member NoteProperty Code $strDiff
$strArr[$i] | Add-Member NoteProperty CppName $strName
$arrDiff += $strArr[$i]
}
}
if ( $Cpp.IsPresent ) {
$arrDiff | Select-Object -Property Code, Mode, LastWriteTime, Length, CppName | ft
} else {
$arrDiff | Select-Object -Property Code, Mode, LastWriteTime, Length, Name | ft
}
<强>输出强>:
PS D:\PShell> .\SO\43381802b.ps1 'C:\testC\43381802'
Code Mode LastWriteTime Length Name
---- ---- ------------- ------ ----
UCS2 -a---- 02/05/2017 11:47:53 317 MailCliеnt.txt
UCS2 -a---- 02/05/2017 11:49:04 317 МailClient.txt
UCS2 -a---- 02/05/2017 11:50:16 399 МailCliеnt.txt
PS D:\PShell> .\SO\43381802b.ps1 'C:\testC\43381802' -Cpp
Code Mode LastWriteTime Length CppName
---- ---- ------------- ------ -------
UCS2 -a---- 02/05/2017 11:47:53 317 MailCli\u0435nt.txt
UCS2 -a---- 02/05/2017 11:49:04 317 \u041CailClient.txt
UCS2 -a---- 02/05/2017 11:50:16 399 \u041CailCli\u0435nt.txt
PS D:\PShell> .\SO\43381802b.ps1 'C:\testC\43381802' -Cpp -All
Code Mode LastWriteTime Length CppName
---- ---- ------------- ------ -------
ANSI -a---- 02/05/2017 11:44:05 235 MailClient.txt
UCS2 -a---- 02/05/2017 11:47:53 317 MailCli\u0435nt.txt
UCS2 -a---- 02/05/2017 11:49:04 317 \u041CailClient.txt
UCS2 -a---- 02/05/2017 11:50:16 399 \u041CailCli\u0435nt.txt
使用以下43381802a.ps1
脚本获取有关非ANSI字符的更多信息(请参阅下面的第一个调用)及其在文件名中的位置(请参阅后面的-Detail
切换后的调用):< / p>
param( [string[]] $strArr = @('ΗGreek', 'НCyril', 'HLatin'),
[switch]$Detail )
Set-StrictMode -Version latest
$auxArr = @()
if ( ( Get-Command -Name Get-CharInfo -ErrorAction SilentlyContinue ) -and
( -not $Detail.IsPresent ) ) {
$auxArr = $strArr | Get-CharInfo |
Where-Object { [int]$_.Codepoint.Replace('U+', '0x') -ge 128 }
} else {
foreach ($strStr in $strArr) {
for ($i = 0; $i -lt $strStr.Length; $i++ ) {
if ( [int][char]$strStr[$i] -ge 128 ) {
$auxArr += [PSCustomObject] @{
Char = $strStr[$i]
CodePoint = 'U+{0:x4}' -f [int][char]$strStr[$i]
Category = $i + 1 ### 1-based index
Description = $strStr ### string itself
}
}
}
}
}
$auxArr
<强>输出强>:
PS D:\PShell> .\SO\43381802a.ps1 ( Get-childitem -path 'C:\testC\43381802' ).Name
Char CodePoint Category Description
---- --------- -------- -----------
е U+0435 LowercaseLetter Cyrillic Small Letter Ie
М U+041C UppercaseLetter Cyrillic Capital Letter Em
М U+041C UppercaseLetter Cyrillic Capital Letter Em
е U+0435 LowercaseLetter Cyrillic Small Letter Ie
PS D:\PShell> .\SO\43381802a.ps1 ( Get-childitem -path 'C:\testC\43381802' ).Name -detail
Char CodePoint Category Description
---- --------- -------- -----------
е U+0435 8 MailCliеnt.txt
М U+041c 1 МailClient.txt
М U+041c 1 МailCliеnt.txt
е U+0435 8 МailCliеnt.txt
经过测试:
==> dir /-C /X /A-D C:\testC\43381802\
Volume in drive C has no label.
Volume Serial Number is …
Directory of C:\testC\43381802
02/05/2017 11:44 235 MAILCL~1.TXT MailClient.txt
02/05/2017 11:47 317 MAILCL~2.TXT MailCliеnt.txt
02/05/2017 11:49 317 AILCLI~1.TXT МailClient.txt
02/05/2017 11:50 399 AILCLI~2.TXT МailCliеnt.txt
4 File(s) 1268 bytes
0 Dir(s) 69914857472 bytes free
==>