I would like to know if there is any way to achieve this behavior on windows, for example:
/b?n/ca? /etc/pa??wd -> executes 'cat /etc/passwd'
I would like to know if there is any way to achieve this behavior on windows, for example:
/b?n/ca? /etc/pa??wd -> executes 'cat /etc/passwd'
In PowerShell you can use Resolve-Path which Resolves the wildcard characters in a path, and displays the path contents.
Example: I want to locate signtool.exe from the Windows SDK which typically resides in "c:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64\signtool.exe" where there could be any other version(s) installed.
So I could use: Resolve-Path 'c:\program*\Windows Kits\10\bin\*\x64\signtool.exe'
EDIT:
If you want to execute it directly you can use the &
invocation operator e.g.
&(Resolve-Path 'c:\wind?ws\n?tepad.exe')
Resolve-Path 'c:\w?ndows\win.ini' | gc | select-string 'fonts'
–
Lineberry Resolve-Path
is a good tool to resolve wildcard paths. For the case of executing a program you don't need it though: & 'c:\wind?ws\n?tepad.exe'
works perfectly fine. –
Cristophercristy With limited exceptions in PowerShell, on Windows there is no support for shell-level globbing - target commands themselves must perform resolution of wildcard patterns to matching filenames; if they don't, globbing must be performed manually, up front, and the results passed as literal paths; see the bottom section for background information.
PowerShell:
Perhaps surprisingly, you can invoke an executable by wildcard pattern, as zett42 points out, though that behavior is problematic (see bottom section):
# Surprisingly DOES find C:\Windows\System32\attrib.exe
# and invokes it.
C:\Windows\System3?\attr*.exe /?
Get-Command
cmdlet.Many file-processing cmdlets in PowerShell do perform their own globbing (e.g., Get-ChildItem
, Remove-Item
); if you're calling commands that do not, notably external programs that don't, you must perform globbing manually, up front, except on Unix-like platforms when calling external programs, where PowerShell does perform automatic globbing (see bottom section):
Use Convert-Path
to get the full, file-system-native paths of matching files or directories.
Resolve-Path
may work too, it returns objects whose .ProviderPath
property you need to access to get the same information (stringifying these objects, as happens implicitly when you pass them to external programs, yields their .Path
property, which may be based on PowerShell-only drives that external programs and .NET APIs know nothing about.)For more control over what is matched, use Get-ChildItem
and access the result objects' .Name
or .FullName
property, as needed; for instance, Get-ChildItem
allows you to limit matching to files (-File
) or directories (-Directory
) only.
PowerShell makes it easy to use the results of manually performed globbing programmatically; the following example passes the full paths of all *.txt
files in the current directory to the cmd.exe
's echo
command as individual arguments; PowerShell automatically encloses paths with spaces in "..."
, if needed:
cmd /c echo (Get-ChildItem -Filter *.txt).FullName
Generally, note that PowerShell's wildcard patterns are more powerful than those of the host platform's file-system APIs, and notably include support for character sets (e.g. [ab]
) and ranges (e.g. [0-9]
); another important difference is that ?
matches exactly one character, whereas the native file-system APIs - both on Windows and Unix-like platforms - match none or one.
-Filter
parameter of file-processing cmdlets such as Get-ChildItem
, it is the host platform's file-system APIs that are used, which - while limiting features (as noted) - improves performance.cmd.exe
(Command Prompt, the legacy shell):
cmd.exe
does not support calling executables by wildcard pattern; some of cmd.exe
's internal commands (e.g., dir
and del
) and some standard external programs (e.g., attrib.exe
) do perform their own globbing; otherwise you must perform globbing manually, up front:
where.exe
, the external program for discovering external programs fundamentally only supports wildcard patterns in executable names (e.g. where find*.exe
), not in paths, which limits wildcard-based lookups to executables located in directories listed in the PATH
environment variable.
:: OK - "*" is part of a *name* only
where.exe find*.exe
:: !! FAILS: "*" or "?" must not be part of a *path*
:: !! -> "ERROR: Invalid pattern is specified in "path:pattern"."
where.exe C:\Windows\System32\find*.exe
Globbing via dir
appears to be limited to wildcard characters in the last path component:
:: OK - "*" is only in the *last* path component.
dir C:\Windows\System32\attri*
:: !! FAILS: "*" or "?" must not occur in *non-terminal* components.
:: !! -> "The filename, directory name, or volume label syntax is incorrect."
dir C:\Windows\System3?\attri*
Using manual globbing results programmatically is quite cumbersome in cmd.exe
and requires use of for
statements (whose wildcard matching has the same limitations as the dir
command); for example, using the syntax for batch files (.cmd
or .bat
files):
To use the resolved executable file path for invocation (assuming only one file matches):
@echo off
setlocal
:: Use a `for` loop over a wildcard pattern to enumerate
:: the matching filenames - assumed to be just *one* in this case,
:: namely attrib.exe, and save it in a variable.
for %%f in (C:\Windows\System32\attr*.exe) do set "Exe=%%f"
:: Execute the resolved filename to show its command-line help.
"%Exe%" /?
To pass matching filenames as multiple arguments to a single command:
@echo off
setlocal enableDelayedExpansion
:: Use a `for` loop over a wildcard pattern to enumerate
:: matching filenames and collect them in a single variable.
set files=
for %%f in (*.txt) do set files=!files! "%%f"
:: Pass all matching filenames to `echo` in this example.
echo %files%
On Unix-like platforms, POSIX-compatible shells such as Bash themselves perform globbing (resolving filename wildcard patterns to matching filenames), before the target command sees the resulting filenames, as part of a feature set called shell expansions (link is to the Bash manual).
On Windows, cmd.exe
(the legacy shell also known as Command Prompt) does NOT perform such expansions and PowerShell mostly does NOT.
That is, it is generally up to each target command to interpret wildcard patterns as such and resolve them to matching filenames.
That said, in PowerShell, many built-in commands, known as cmdlets, do support PowerShell's wildcard patterns, notably via the -Path
parameter of provider cmdlets, such as Get-ChildItem
.
Additionally and more generally, cmdlet parameters that represent names often support wildcards too; e.g., Get-Process exp*
lists all processes whose image name start with exp
, such as explorer
.
Note that the absence of Unix-style shell expansions on Windows also implies that no semantic distinction is made between unquoted and quoted arguments (e.g., *.txt
vs. "*.txt"
): a target command generally sees both as verbatim *.txt
.
In PowerShell, automatic globbing DOES occur in these limited cases:
Perhaps surprisingly, an executable file path can be invoked via a wildcard pattern:
as-is, if the pattern isn't enclosed in '...'
or "..."
and/or contains no variable references or expressions; e.g.:
C:\Windows\System3?\attri?.exe
via &
, the call operator, otherwise; e.g.:
& $env:SystemRoot\System32\attri?.exe
However, this feature is of questionable utility - When would you not want to know up front what specific executable you're invoking? - and it is unclear whether it was implemented by design, given that inappropriate wildcard processing surfaces in other contexts too - see GitHub issue #4726.
Additionally, up to at least PowerShell 7.2.4, if two or more executables match the wildcard pattern, a misleading error occurs, suggesting that no matching executable was found - see GitHub issue #17468; a variation of the problem also affects passing a wildcard-based path (as opposed to a mere name) that matches multiple executables to Get-Command
.
In POSIX-compatible shells, the multi-match scenario is handled differently, but is equally useless: the first matching executable is invoked, and all others are passed as its arguments.
On Unix-like platforms only, PowerShell emulates the globbing feature of POSIX-compatible shells when calling external programs, in an effort to behave more like the platform-native shells; if PowerShell didn't do that, something as simple as ls *.txt
would fail, given that the external /bin/ls
utility would then receive verbatim *.txt
as its argument.
`
-escape wildcard metacharacters in order to suppress globbing - see GitHub issue #18038In PowerShell you can use Resolve-Path which Resolves the wildcard characters in a path, and displays the path contents.
Example: I want to locate signtool.exe from the Windows SDK which typically resides in "c:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64\signtool.exe" where there could be any other version(s) installed.
So I could use: Resolve-Path 'c:\program*\Windows Kits\10\bin\*\x64\signtool.exe'
EDIT:
If you want to execute it directly you can use the &
invocation operator e.g.
&(Resolve-Path 'c:\wind?ws\n?tepad.exe')
Resolve-Path 'c:\w?ndows\win.ini' | gc | select-string 'fonts'
–
Lineberry Resolve-Path
is a good tool to resolve wildcard paths. For the case of executing a program you don't need it though: & 'c:\wind?ws\n?tepad.exe'
works perfectly fine. –
Cristophercristy © 2022 - 2024 — McMap. All rights reserved.
/bin/cat
executable in Windows). Simply use the&
invocation operator andGet-Command
(aliasgcm
):& (gcm 'Get-C?nte?t') .\spycloud.py
– Desalinate