I am trying to find files from a directory:
String[] search1 = Directory.GetFiles(voiceSource, "85267-*.wav")
.Select(path => Path.GetFileName(path))
.ToArray();
String[] search2 = Directory.GetFiles(voiceSource, "85267 *.wav")
.Select(path => Path.GetFileName(path))
.ToArray();
But in search1
, it selects both 85267-s.wav
and 85267 -s.wav
. But I want only 85267-s.wav
to be selected.
search2
is doing well.
How can I do that?
Command. When you use the wildcard character (*) at both the ends, file name containing that string will be displayed. For example, the below command will display all the files which contain the word “tmp”.
There are two wildcard characters: asterisk (*) and question mark (?). Asterisk (*) - Use the asterisk as a substitute for zero or more characters. e.g., friend* will locate all files and folders that begin with friend. Question mark (?)- Use the question mark as a substitute for a single character in a file name.
When you have a number of files named in series (for example, chap1 to chap12) or filenames with common characters (like aegis, aeon, and aerie), you can use wildcards (also called metacharacters) to specify many files at once. These special characters are * (asterisk), ? (question mark), and [ ] (square brackets).
Can be used by: Standard wildcards are used by nearly any command (including mv, cp, rm and many others). this can represent any single character. If you specified something at the command line like "hd?" GNU/Linux would look for hda, hdb, hdc and every other letter/number between a-z, 0-9.
The behaviour you are experiencing is because of short file name. Since you will get 85267-~1.WAV
for 85267 -s.wav
and since that matches your wild card "85267-*.wav"
you get both files back.
The is explained in Directory.GetFiles Method (String, String)
Because this method checks against file names with both the 8.3 file name format and the long file name format, a search pattern similar to "1.txt" may return unexpected file names. For example, using a search pattern of "1.txt" will return "longfilename.txt" because the equivalent 8.3 file name format would be "longf~1.txt".
For workaround you can use Directory.EnumerateFiles
to first select both files matching your criteria and then compare the actual(long) file name part using StartsWith
. Remember EnumerateFiles
does lazy evaluation.
String[] search1 = Directory.EnumerateFiles(@"C:\test", "85267-*.wav")
.Where(file => Path.GetFileName(file).StartsWith("85267-"))
.Select(path => Path.GetFileName(path))
.ToArray();
Yes, this is a side-effect of the MS-Dos 8.3 short name support that's still turned on today on most file systems. Something you can see with the DIR /X command, it displays those short names. On my machine:
C:\temp>dir /x *.wav
01/21/2015 09:11 AM 6 85267-~1.WAV 85267 -s.wav
01/21/2015 09:11 AM 6 85267-s.wav
2 File(s) 12 bytes
0 Dir(s) 235,121,160,192 bytes free
Note how the short name for "85267 -s" is missing the space. It is not a valid character in a short name. What's left over now also matches your wildcard.
That's not where the trouble ends with those short names, A wildcard like *.wav
will also match a file like foobar.wavx
, a completely different file type.
Short-name generation is, frankly, a relic from the previous century that ought to be turned off today. But that is not typically anything you can control yourself. You have to deal with these accidental matches and double-check what you get back. With a Regex for example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With