我需要比较两个包含大量文件(例如comp d1\*.* d2\*.*
)的目录是否相等。 for
循环逐个比较文件太慢了。我只在乎所有文件是否都存在并且相等。换句话说,我只关心comp.exe
返回码。
但是,当存在以句点开头的文件时,出现意外错误。例如,如果我执行以下操作:
md d1
echo x >d1\.file
md d2
echo x >d2\.file
comp d1\*.* d2\*.*
它产生:
d1\.file d2\*.*
Could not expand second file name so as to match first
用
comp
替换fc
会产生相同的结果。我不知道为什么会这样-目录应该完全相等-想知道是否有解决方法。
最佳答案
打开命令提示符窗口,然后运行comp /?或fc /?并阅读输出的简短帮助。或阅读两个参考的Microsoft帮助页面以及Microsoft command line reference中的示例。
我们必须澄清一些术语以理解该问题。
Windows上文件的名称由两部分组成:
文件名是文件名中最后一个.
保留的所有内容。
文件扩展名是最后一个.
,所有扩展名都以文件名开头。
好吧,最后一个.
实际上是文件名和文件扩展名之间的分隔符。因此,最后一个.
之后的字符串实际上是文件扩展名。但是,点/点也必须属于文件名或文件扩展名,以仅将文件名的两部分串联即可构建。因此,最后一个点被添加到文件扩展名中。
因此,在Windows上,文件名为.file
的文件具有空文件名,并且.file
作为文件扩展名,可以在命令提示符窗口中运行时看到:
@for %I in (.file) do @echo File name="%~nI" & echo File extension="%~xI"
输出为:
File name=""
File extension=".file"
在Unix / Linux上,没有这样的文件名定义,该文件名由两部分组成,尽管Unix / Linux上的许多文件也具有name.ext语法,因为这使人们更容易获得有关文件类型的信息(png,jpg, sh,txt,...)。
所有Windows文件系统都支持hidden属性,以将文件或目录标记为隐藏。 Unix / Linux文件系统没有这样的属性。在Unix / Linux上,当目录或文件的名称以
.
开头时,其解释为隐藏。因此,在Unix / Linux上,像.file
这样的文件会被解释为名称为file
的隐藏文件。 .htaccess
是Linux Web服务器上非常常见的隐藏文件,其名称以真实的htaccess
表示,而开始处的点将该文件标记为在Unix / Linux上隐藏。好的。那么,在比较仅包含一个文件和以
d1
作为文件名的目录d2
和.file
的问题是什么?这两个文件没有文件名。但是两个compare命令都需要使用通配符使用文件名部分来从两个目录中识别出这两个文件进行比较。这就是Windows上这两个比较命令用于比较两个目录中的多个文件的方式。
工作是:
comp d1\.file d2\.file
fc d1\.file d2\.file
但是,如果与通配符模式匹配的两个目录之一中的一个文件具有空文件名,则无法与通配符进行比较。在这种特殊情况下,
comp.exe
中的两个控制台应用程序fc.exe
和%SystemRoot%\System32
无法在另一个目录中找到匹配的文件,该目录也没有文件名,只是一个匹配的文件扩展名。使用的命令行
comp d1\*.* d2\*.*
也可以写为comp d1\* d2\*
,因为Windows总是像*.*
那样解释*
。这可以在运行dir *.*
时看到,该命令还会查找根本不包含.
的文件夹和文件。使用
comp d1\*.* d2\*.*
时,控制台应用程序COMP首先搜索目录d1
中的任何文件,在这种情况下,将找到文件.file
。它将此文件的名称分为文件名和文件扩展名。文件名是一个空字符串,长度为0。编写COMP以便在其他目录
d2
中搜索与第一个目录中找到的文件具有相同文件名的文件,该文件具有在命令行上指定的文件扩展名作为第二个参数。在这种情况下,命令行上指定的文件扩展名也为*
,表示任何文件扩展名。因此,COMP不应搜索任何内容。*或更确切地说,是在文件夹
.*
中搜索d2
,因为名称为文件.file
的文件没有文件名。与
dir .*
或dir *
相比,dir *.*
输出什么?dir .*
仅输出以点开头的文件和文件夹名称,而dir *
和dir *.*
输出当前目录中的所有文件和文件夹。因此,COMP应该可以在
.file
中找到文件d2
。但是,如果COMP找到一个空文件名的文件,它甚至不会在其他目录中运行此搜索,而是输出错误消息。
有趣的是,在这种特殊用例中不起作用:
comp d1\* d2\*
comp d1\*.* d2\*.*
comp d1\.file d2\*
comp d1\.file d2\*.*
comp d1\.file d2\*.file
但是工作是在这种特殊的用例中:
comp d1\* d2\.file
comp d1\*.* d2\.file
comp d1\*.file d2\.file
(对我而言)这是一个非常清晰的指示,表明编写COMP和FC代码的开发人员没有考虑到特殊用例。用户通常将应用程序对这种不正确处理的用例的评价为BUG。
解决COMP和FC错误的一种简单解决方案是使用其他目录比较工具,例如Beyond Compare,UltraCompare等,可以正确处理这种特殊情况。
可能的解决方法是,通过在开始处插入
###
来临时重命名以点开头的文件,运行目录比较,然后将以###
开头的文件重命名为原始名称。@echo off
ren d1\.* ###.* 2>nul
ren d2\.* ###.* 2>nul
echo N | %SystemRoot%\System32\comp.exe d1\* d2\* >nul 2>&1
if errorlevel 1 ( set "Result=different" ) else set "Result=identical"
echo Folders d1 and d2 are %Result%.
ren d1\###.* .* 2>nul
ren d2\###.* .* 2>nul
当然,如果两个目录之一中已经存在文件名开头带有
###
的文件,则此简单的解决方法将无法正常工作。
关于batch-file - 比较Win 7中的目录时发生意外错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47108687/