6

On Windows 7, I have a directory containing the following four files:

  • xxx.txt
  • xxx.txt2
  • xxx2.txt
  • xxx2.txt2

With the file have more than 3 character as a file extension, the behavior of the wildcard * seems odd:

dir *.txt

10/13/2014  04:14 PM                 6 xxx.txt
10/13/2014  04:17 PM                 6 xxx2.txt
10/13/2014  04:17 PM                 6 xxx2.txt2
10/13/2014  04:14 PM                 6 xxx.txt2
           4 File(s)             24 bytes
           0 Dir(s)   6,660,980,736 bytes free

I would expect to see only the two files with txt extension and not the ones with txt2 (like it would on a Linux machine). Does MS-DOS ignore the truncate the file extension to 3 characters or does it add automatically another wildcard at the end? If I want to delete only the files with txt extension and not the one with txt2, which command should I use? Thanks

7

You're not using MS-DOS; it did not even allow file extensions longer than 3 characters. You're using the Windows command line – the cmd.exe shell, specifically.

But Windows indeed tries hard to remain compatible with programs from that era. So, up until Windows 8 (or something like that), all files with longer extensions have an alias that has the extension truncated, along with the name itself.

If you run dir /x, you'll likely see that each file has a "short name" assigned to it, which is limited to 8+3 characters, just like in MS-DOS and 16-bit Windows.

These names are there in case the user wanted to, let's say, upgrade to Windows 95 and still access their files through programs originally written for Windows 3.1 – so running a 16-bit program wouldn't crash, but would merely show C:\PROGRA~1 and C:\MYDOCU~1\CALENDAR.TXT in place of C:\Program Files and C:\My Documents\Calendar.txt.

(And yes, some people did actually use old 16-bit software even in Windows XP/Vista days... I'm pretty sure Windows 8 turn off the "short names" by default, however. This might be why @EBGreen isn't seeing the same 'problem'...)


Another thing to consider is that the old Windows shell, cmd.exe, has grown quite a few quirks and compatibility fixes in itself. For example, due to the way MS-DOS matched filenames, dir .txt meant the same as dir *.txt, even though it wasn't intentional. But people got used to the shorter syntax, and even though the Windows operating system itself doesn't treat .txt as a wildcard anymore, cmd.exe still accepts that syntax. (The dir command isn't a program on its own, but built into the shell.)

(Similarly, in the linked article, another wildcard quirk is described – Windows filenames can have no extension at all, but people are really used to typing *.*, therefore it means the same thing as * and the lone dot is ignored.)

  • Just to be clear, I do see the same behavior as the OP. I will also add that trying to use the 8.3 name of the files would still not work since the first part of the file name gets changed to do the 8.3 name and the extension would be changed to .txt in this example so trying to wildcard on the extension still would not work even using dir /x – EBGreen Oct 13 '14 at 14:56
  • dir /x doesn't use the short names, it merely shows them. The short names are used automatically in any situation where the long names work. That is, whenever a program asks the OS to match wildcards, the OS will consider both the short and long name, and the short one will match. – user1686 Oct 13 '14 at 15:04
  • I was aware of the short name (and use it sometimes for programs that do not accept path names containing spaces) but I did not know wildcards would match those as well. Would there be an alternative method to remove all files with a given extension and ignore the other ones? I'm thinking something like "dir|findstr \....$|del"? – tristof Oct 14 '14 at 9:43
  • 1
    @tristof: Yes, or perhaps for %f in (*) if "%~xf"==".txt" ..., as merely iterating over the directory will only return long names. – user1686 Oct 14 '14 at 9:53
  • 1
    The question says, “If I want to delete only the files with txt extension and not the one with txt2, which command should I use?”  My eyesight is failing; I don’t see where you answered that question (you explain why the OP has the problem they have, but not how to fix it) except in that last comment.  Can you put the answer into the answer, please?  (See also DOS — moving specific .xml file extension.) – Scott Oct 5 '18 at 19:17
3

I can't tell you why it works that way. It is quite odd. What I can tell you is that Powershell (which you should have on the machine) works the way that you expect. In powershell:

PS I:\temp\test> ls


    Directory: I:\temp\test


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        10/13/2014   9:29 AM          3 bar.txt
-a---        10/13/2014   9:29 AM          3 bar.txt2
-a---        10/13/2014   9:29 AM          3 foo.txt
-a---        10/13/2014   9:29 AM          3 foo.txt2

PS I:\temp\test> ls *.txt


    Directory: I:\temp\test


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        10/13/2014   9:29 AM          3 bar.txt
-a---        10/13/2014   9:29 AM          3 foo.txt
2

grawity correctly identified that the behavior stems from short file names. Filemasks are compared to both the long and short names.

The full rules for how wild cards are matched against file names is available in the "sourceMask" section of How does the Windows RENAME command interpret wildcards?

You can get your desired DIR result by piping to FINDSTR:

dir *.txt* | findstr /vrix "[0-9].*\.txt[^.][^.]*"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.