Is there any way to get the windows cmd shell to expand wildcard paths?

DOS, and consequently Windows' cmd.exe, never supported wildcard expansion by the shell. It was always up to the application to do the expansion.

This means you will always have to find another route if you're using an application that doesn't support expansion. You could:

  • Use a FOR loop to run some commands against all the files you're interested in
  • Use dir /b > list.txt to use the dir command to perform the expansion and put the list of files into a text file (you could then use something like an Excel formula if you're really desperate to produce a list of commands to paste into cmd, or you could use Excel to transpose the cells so all the filenames are on the same line.)

This will give you a list and also put it in variable named expanded_list. Put it in batch file and run with myBatchFile name myPattern. Enclose pattern with quotation marks if it includes spaces. Matches files, no dirs. Run without parameters matches all.

@echo off
set expanded_list=
for /f "tokens=*" %%F in ('dir /b /a:-d "%~1"') do call set expanded_list=%%expanded_list%% "%%F"

echo expanded_list is: 
echo %expanded_list%

You can then run you command with my_command_exec %expanded_list%

WARNING! Maximum size of cmd variable is 8191 characters (XP onwards), so it's possible to overflow it! You cannot count on the utility to always give you complete list. On the other hand, maximum cmd line length is also 8191 so you would not be able to execute it anyway.


Just use Powershell, which is preinstalled on Windows 7. Powershell is capable of running cmd commands and does understand wildcards at any place in a path.

To start Powershell just type "powershell" in your start menu search box and hit enter.


In case the application expects a string with all filenames in it this is the right script:

$delimiter = " "
[string]$files = $nothing ; ls *.txt | % { $files += $_.fullname + $delimiter } ; application.exe $files

Change $delimiter = " " to $delimiter = "," if your application expects a comma separated list of file names.

Explanation of code:

  • [string]$files = $nothing - creates an empty variable of type string
  • ; - is a separator for multiple commands, not a pipeline!
  • ls *.txt | % { $files += $_.fullname + $delimiter } - gets a list of all text files and creates a string with all filenames separated by the delimiter
  • application.exe $files - calls the application and passes the file list to it

You can even search for a file pattern recursively by adding -recurse to ls *.txt so the complete code would look like this:

$delimiter = " "
[string]$files = $nothing ; ls *.txt -recurse | % { $files += $_.fullname + $delimiter } ; application.exe $files

Edit:
To avoid irritations, ls and dir are aliases of Get-ChildItem and % is an alias to ForEach-Object. I keep my code with aliases used because it's shorter.

EDIT 2018/04/25:
Back in 2012 I've been fairly new to PowerShell. Of course there is an easier way though it's not as easy as unix/linux' capability of glob expansion:

app.exe $(ls *.txt | % {$_.FullName})

Explanation:

  • $() will evaluate the expression inside first and will replace itself with the output of that expression (much like backticks do in bash)
  • ls *.txt gets FileInfo objects of all files that match the glob *.txt
  • because PowerShell is object oriented, we have to output the fullname of each FileInfo object. Simply naming an attribute/property in PowerShell outputs it by default. % { $_.FileName } does that for us. % loops over all elements returned by ls and outputs each objects FileName.