21

I've used the setargv.obj linking for expanding wildcard arguments in the past for a number of C and C++ applications, but I can't find any similar mention for .NET applications.

Is there a standard way to have your application's command line parameters automatically wildcard expanded? (i.e., expand *.doc from one entry in the args parameter to all that match that wildcard).

P.S.: I've hacked something together with Directory.GetFiles() for my current little project, but it does not cover wildcards with paths (yet), and it would be nice to do it without custom code.

Here is my rough hack, for illustration. It needs to split the parameters for the path and name for the GetFiles(), but this is a general idea. Linking setargv.obj into a C or C++ application would basically do all the wildcard expansion, leaving the user to only iterate over the argv array.

public static void Main(string[] args) { foreach (string argString in args) { // Split into path and wildcard int lastBackslashPos = argString.LastIndexOf('\\') + 1; path = argString.Substring(0, lastBackslashPos); filenameOnly = argString.Substring(lastBackslashPos, argString.Length - lastBackslashPos); string[] fileList = System.IO.Directory.GetFiles(path, filenameOnly); foreach (string fileName in fileList) { // Do things for each file } } } 
6
  • By that do you mean not only wildcard file names but wildcard folder names too? For example something like: C:\Windows\System32*\Test*.doc ? Commented Dec 19, 2008 at 16:09
  • The "original" setargv.obj would only work with wildcards in the file name, so that is what I'm looking for. Commented Dec 19, 2008 at 16:46
  • that doesn't look like a hack at all, it looks pretty straight forward. Commented Dec 23, 2008 at 0:51
  • doesn't the shell do that for you? Commented Dec 23, 2008 at 1:39
  • 2
    Unfortunately the Windows shell doesn't expand things. Something about re-inventing unix poorly. Also this doesn't work with ..\ in the wildcard path. Commented Apr 17, 2009 at 18:49

4 Answers 4

9

Here is my rough hack. I'd love for it to be recursive. And having experienced the shortcoming of Windows wildcards, I might decide to use regular expressions rather than letting GetFiles() do it for me.

using System.IO; public static string[] ExpandFilePaths(string[] args) { var fileList = new List<string>(); foreach (var arg in args) { var substitutedArg = System.Environment.ExpandEnvironmentVariables(arg); var dirPart = Path.GetDirectoryName(substitutedArg); if (dirPart.Length == 0) dirPart = "."; var filePart = Path.GetFileName(substitutedArg); foreach (var filepath in Directory.GetFiles(dirPart, filePart)) fileList.Add(filepath); } return fileList.ToArray(); } 
Sign up to request clarification or add additional context in comments.

Comments

4

I'm not sure exactly what you're after... but if I get where you're going with the Directory.GetFiles() "hack" you mentioned, then something like this might work:

var Dirs = Directory.GetDirectories(@"C:\Windows", "sys*", SearchOption.TopDirectoryOnly).ToList(); var Files = new List<String>(); Dirs.ForEach(dirName => Files.AddRange(Directory.GetFiles(dirName, "*.sys", SearchOption.AllDirectories))); 

The wildcard option on the GetDirectories call will allow you to grab all the directories contained in the Windows folder [directly] that match the pattern "sys*".

You can then iterate over those folders grabbing all the files that match the pattern "*.sys".

Is that the kind of thing you're looking for? To automatically expand the args, you'd have to extract the wildcards in some kind of meaningful manner and apply them to that model...

For instance:

RunMyApp "C:\Windows\Sys*\ *.sys"

You'd pull out the string C:\Windows - probably with a regular expression, find the lowest level directory that doesn't contain a wildcard and apply it to the GetDirectories method, attaching the wildcarded string as the search parameter.

Then if your end of string (in this case *.sys) as the search pattern for Directory.GetFiles.

If you wanted to get more complicated and do something like:

C:\Windows\*\Sys*\*.sys 

You would use the SearchOptions to set this behaviour:

Directory.GetDirectories(@"C:\Windows", "sys*", SearchOptions.AllDirectories) 

This would grab all directories that matched the sys* wildcard in the Windows directory and all directories below it.

If you wanted to get much more complicated than that, then I'm not sure how you would do that... for instance, say you wanted folders that are contained by folders directly inside the Windows directory - I have no idea how you would go about something like that I'm afraid...I don't imagine exporting the entire tree structure to XML and using XPath to do it would be so efficient - the XPath would be fabulously simple for parsing out using wildcards - but converting to XML wouldn't be so efficient...

2 Comments

Thanks for the examples. The C/C++ method would only expand file names, as far as I remember. My main question is if there is a way to do it like the C/C++ method without writing your own code (like I've done). Although .net makes it easier that it would have been in C/C++!
@crashmstr: I won't say there definitely isn't - there's too many hidden corners of the .NET framework. As far as I'm aware however, there's no native way of doing that automatically.
3

See the source code of the disassembled Microsoft.Build.Shared.FileMatcher class in Microsoft.Build.dll. You can get some idea from the implementation of method GetFiles.

As a client, you may use the method as follows:

var filelist = FileMatcher.GetFiles(@"c:\alaki", @"c:\alaki\**\bin\*.dll"); 

3 Comments

Good find... if only that class wasn't internal.
Can you add some references to it? It isn't very search engine friendly. NuGet package Microsoft.Build (which mentions Microsoft.Build.dll). An unanswered Stack Overflow question: Is there a opensource equivalent to the FileMatcher class in MSBuild? (without any related question(!!!)).
Had it been posted after December 2022 (and not more than 10 years ago) without references, the index of suspicion would have been high for a bogus ChatGPT hallucination.
1

Your code looks like exactly how you're supposed to do it.

1 Comment

True, but in C/C++ there is a mechanism in the compiler to do the work for you. At least it is much easier in .net to do this.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.