奇怪的Windows DIR命令行为

18

我无意中发现了这个问题,当我在寻找一个文件名中带有数字的文件时。当我在命令提示符(cmd.exe)中键入:

dir *数字*

(其中数字代表从0到9的任何数字,并且在星号和数字之间没有空格)

它会返回一些不符合搜索条件的文件。奇怪的是,根据目录的不同,有些数字可以使用,而有些则不行。例如,在与网站相关联的目录中,我键入以下内容:

dir *4*

返回的结果如下:

C:\Ampps\www\includes\pages目录
04/30/2012 03:55 PM 153 inventory_list_retrieve.php 06/18/2012 11:17 AM 6,756 ix.html 06/19/2012 01:47 PM 257,501 jquery.1.7.1.js 共 3 个文件 264,410 字节 0 个目录 362,280,906,752 字节可用

这对我来说毫无意义。你有什么线索吗?

该问题在stackOverflow上发布,因为DIR命令经常与批处理程序中的FOR组合使用。奇怪的DIR行为似乎会使批处理程序在使用DIR命令时变得不可靠。

编辑:(附加说明)。虽然时间过去了很长时间,但我发现它还有另一个怪异之处,这几乎让我付出了很多工作。我想删除特定目录树中所有的 .htm 文件。我意识到就在执行操作之前, * .htm 也匹配 .html 文件。同样, * .man 匹配 .manifest 文件,可能还有其他文件。删除特定目录中的所有 .html 文件将是非常沮丧的。


1
有趣!我们需要对这个问题进行一些测试... - Aacini
1
哇,经过这么多年,我仍然对这项技术感到惊叹。我可以确认那种奇怪的行为。 - Helbreder
http://superuser.com/questions/336358/is-it-a-good-idea-to-disable-short-filenames-on-windows-7-running-on-a-ssd-drive - Hans Passant
5
虽然这个问题没有明确涉及到批处理编程,但是其中潜在的问题对于批处理编程有着深刻的影响。请不要因为它与编程无关而关闭此问题。 - dbenham
5
如果有能力反对关闭的投票,我会进行投票。如果问题被关闭,我会投票重新开放。这触及到了Windows API在命令提示符和批处理文件中的基本问题。在我看来,这显然与批处理和cmd标签相关。 - RBerteig
请展示一下你在批处理文件中调用dir命令的部分代码,这样就不会再次被迁移了。 - casperOne
4个回答

17
在命令提示符中,通配符将与长文件名和短的“8.3”名称(如果存在)匹配。这可能会产生意外情况。 要查看短名称,请使用DIR命令的/X选项。 请注意,此行为与DIR命令无关,并且当通配符在任何命令上匹配超出预期时(例如DEL),可能会导致其他(通常不愉快的)意外情况。 与*nix shell不同,文件模式的替换与匹配名称列表的实现是在每个命令内部实现的,而不是由shell本身实现的。这可能意味着不同的命令可以实现不同的通配符模式规则,但在实践中,这种情况非常罕见,因为Windows提供了API调用以搜索匹配模式的目录,并且大多数程序以明显的方式使用这些调用。对于使用“通常”工具编写的C或C ++程序,该扩展由C运行时库免费提供,使用Windows API。
The Windows API涉及的函数是FindFirstFile()以及其相关函数FindFirstFileEx(), FindNextFile(), 和 FindClose()

奇怪的是,虽然FindFirstFile()的文档将其lpFileName参数描述为“目录或路径和文件名,可以包括通配符字符,例如星号(*)或问号(?)”,但它实际上从未定义*?字符的含义。

这个文件模式的确切含义可以追溯到20世纪70年代初的CP/M操作系统,它强烈地影响了MSDOS的设计(有人可能会说“直接复制”而不是“影响”)。这导致了许多“有趣”的现象和行为。其中一些在DOS端的光谱上描述在这篇博客文章中,Raymond描述了DOS中文件模式的实现方式。

13

没错,如果你尝试这样做,你会发现它也会搜索短名称:


dir /x *4*

(/x开关是用于短文件名的)

要过滤文件名,请使用:

dir /b | find "4"

2
如果您只想搜索长名称,请使用 | find 进行搜索。 - npocmaka
2
+1,是的,“隐藏”的短文件名可能会导致不明显的问题。使用FIND的建议应该有效:dir /b | find "4"。而使用FINDSTR则可以通过正则表达式进行更有选择性的过滤。 - dbenham

5

RBerteig的回答中有一句话:

请注意,这种行为与DIR命令无关,并且当通配符在任何命令中匹配超出预期时,例如DEL命令时,可能会导致其他(通常不愉快的)意外情况。

即使对于FOR命令也是如此,它非常讨厌。

for %A in (*4*) do @echo %A contains a 4

将会搜索短名称。解决方法是使用FIND或FINDSTR以更可靠的方式过滤名称。

for %A in (*) do @echo %A | >nul findstr 4 && echo %A contains a 4

注意 - 如果在批处理文件中使用该命令,请将%A更改为%%A。
将FOR与FINDSTR结合使用可以成为一种通用方法,安全地使用任何遇到短文件名问题的命令。只需将ECHO替换为问题命令,例如COPY或DEL。

4

似乎dir命令在底层搜索短(8.3格式)文件名。

当我调用dir *1*时,我得到的结果如下:

 Volume in drive C is System
 Volume Serial Number is F061-0B78

 Directory of C:\Users\Piotrek\Desktop\Downloads
2012-05-20  17:33        23 639 040 gDEBugger-5_8.msi
2012-05-20  17:30           761 942 glew-1.7.0.zip
2012-05-20  17:11         9 330 176 irfanview_plugins_433_setup.exe
2012-05-24  20:17         4 419 192 SumatraPDF-2.1.1-install.exe
2012-05-15  22:55         3 466 248 TrueCrypt Setup 7.1a.exe
               5 File(s)  1 127 302 494 bytes

在列出的文件中有一个名为gDEBugger-5_8.msi的文件,显然它并不包含任何字符1。当我在dir命令中使用开关/X时一切都变得清晰明了,这使得dir使用8.3文件名。使用dir /X *1*命令输出:
 Volume in drive C is System
 Volume Serial Number is F061-0B78

 Directory of C:\Users\Piotrek\Desktop\Downloads


2012-05-20  17:33        23 639 040 GDEBUG~1.MSI gDEBugger-5_8.msi
2012-05-20  17:30           761 942 GLEW-1~1.ZIP glew-1.7.0.zip
2012-05-20  17:11         9 330 176 IRFANV~1.EXE irfanview_plugins_433_setup.exe
2012-05-24  20:17         4 419 192 SUMATR~1.EXE SumatraPDF-2.1.1-install.exe
2012-05-15  22:55         3 466 248 TRUECR~1.EXE TrueCrypt Setup 7.1a.exe
               5 File(s)  1 127 302 494 bytes

来自dir帮助的引用:

/X          This displays the short names generated for non-8dot3 file
            names.  The format is that of /N with the short name inserted
            before the long name. If no short name is present, blanks are
            displayed in its place.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接