The PowerShell equivalent of your foo.bat
file is a foo.ps1
file with the following content:
# Passes all arguments received by this script to bar.exe
bar.exe @args
PowerShell exposes all (unbound) positional arguments[1] as an array stored in the automatic $args
variable.
By prefixing $args
with @
instead of $
, argument splatting is employed, which means that the elements of the $args
array are passed as individual arguments to bar.exe
- Note: This isn't strictly necessary when calling external programs (such as
bar.exe
) - $args
would work there too - but is more versatile in that it can also pass named arguments correctly through to other PowerShell commands, which typically have declared parameters that can be bound by name (e.g., -Path C:\temp
to bind value C:\temp
to declared parameter -Path
)
As for working with $args
in general:
$args.Count
tells you how many (unbound) positional arguments were passed,
$args[0]
returns the first such argument, $args[1]
the second, and so on.
However, it is usually preferable to formally declare parameters in PowerShell scripts and functions, which can then also be bound by name (e.g., -FooParam foo
instead of just foo
). See this answer for more information.
[1] If your script doesn't formally declare any parameters (via a param(...)
block - see about_Scripts and the linked answer), all arguments are by definition unbound (i.e. not mapped to a declared parameter) and positional (not prefixed by a target parameter name). However, if your script does declare parameters, $args
only contains those arguments, if any, that were passed in addition to those binding to declared parameters. If your script is an advanced script (or function), $args
isn't supported at all, because passing unbound arguments is then categorically prevented. See this answer for more information.