的Windows/NTFS:两个文件在同一目录中相同的长的名字?

问题描述:

我一直在*.com一个潜伏者多年(伟大的网站,在这里用户),但从来没有需要问一个问题。现在是时候了:-)让我开始:的Windows/NTFS:两个文件在同一目录中相同的长的名字?

操作系统:x64 Windows 8.0到Windows 10(15063.14)(这个问题存在多年,但我从来没有完全追求它,所以我们可以排除它是具体到特定的Windows版本)

FS:NTFS

问题:2个文件在同一目录相同(长)的名字,我想不通这是怎么都不可能发生。每当我手动升级我的电子邮件客户端时,都会发生这种情况。它的主要.EXE文件(MailClient.exe)永远不会要求替换,如果将新文件复制到同一个目录。相反,它们都放在那里,名字完全一样。

问题无关与特定的目录,我可以绕在NTFS目录开车到新创建的两个.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: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名,OK,但确切同样的长名。这是另一种情况的截图。这两个文件都在Windows“属性”对话框中显示相同的位置(右键单击)。不幸的是,我不允许发布图像(看起来) - 只是尝试。所以你必须接受我的话。

我无法弄清楚这是怎么可能的,而这正在扰乱我;)一旦我将这两个文件重命名为例如1.exe,Windows就会开始告诉我,在同一目录中已经有一个具有该名称的文件。因此很明显有事情做与文件名,但他们都完全相同,没有多余的空格,什么都没有,你可以从DIR命令看到。

我也尝试重命名它们,并手动重写两个字符的确切字词“MailCient.exe”,以确保字符是相同的,Windows仍然不会抱怨,它们都会一次去那里再次以相同的名字。然而,重命名他们“MAIL.EXE”和“MAIL.EXE”都不行,那么Windows是说,与该名称的另一个文件已经存在。但是,将它们都命名为“MailClient.exe”就绝对没问题,没有Windows的抱怨。

这个另一个有趣的事实,如果我DIR为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说(并且正确)以至于具有该名称的文件已经存在。所以它似乎归结为两个文件名中可能具有另一个ANSI字符的“e”?然而,我不知道另一个“e”,还是我错过了什么?

+0

的最佳答案:文件名中的一个包含Unicode字符,只是看起来相同作为ANSI字符。 –

+0

谢谢,根据我的更新#1(重命名测试通过慢慢截断名称然后重建它),这确实是这种情况。我将再次报告有关此:) – Lori

+0

我刚刚[在超级用户上发布了答案](https://超级用户。com/a/1199537/96662)显示了一种方法,让您准确查看文件名中的哪些代码点。 –

Harry Johnston is right:文件名的一个包含Unicode字符,只是看起来同一个ANSI字符

阅读Naming Files, Paths, and Namespaces

在较新的文件系统,如NTFS,exFAT的,UDF和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开关):

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 

==>