7

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

dbenham
  • 11,794
tristof
  • 115
  • 1
  • 6

4 Answers4

10

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.)

grawity
  • 501,077
4

As others have pointed out, this is about short file names generation. But note that this is not system-wide settings. It can be different per volume. I've noticed on my machine that the behavior varies between drives. And indeed, my C: drive has short name generation on, while the D: drive has it off. You can check it with fsutil 8dot3name command (as Admin).

C:\>dir *.txt
 Volume in drive C is Windows
 Volume Serial Number is EC1B-17C1

Directory of C:\

28.08.2023 10:25 10 foo.txt 28.08.2023 10:25 11 FOO~1.TXT foo.txt2 2 File(s) 21 bytes 0 Dir(s) 36 329 230 336 bytes free

C:>fsutil 8dot3name query C: The volume state is: 0 (8dot3 name creation is enabled). The registry state is: 2 (Per volume setting - the default).

Based on the above settings, 8dot3 name creation is enabled on C:

C:>D:

D:>dir *.txt Volume in drive D is Data Volume Serial Number is EFFC-CC70

Directory of D:\

28.08.2023 10:25 10 foo.txt 1 File(s) 10 bytes 0 Dir(s) 309 316 231 168 bytes free

D:>fsutil 8dot3name query D: The volume state is: 1 (8dot3 name creation is disabled). The registry state is: 2 (Per volume setting - the default).

Based on the above settings, 8dot3 name creation is disabled on D:

4

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
EBGreen
  • 9,655
3

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[^.][^.]*"
dbenham
  • 11,794