In order to invoke a script file (.ps1
) with arguments, use the PowerShell CLI's -File
parameter, not the (implied) -Command
parameter:
powershell -File .\test.ps1 "foo bar moo"
Note that PowerShell (Core) (pwsh
, PowerShell versions starting with v6) now defaults to -File
.[1]
As for what you tried:
powershell .\test.ps1 "foo bar moo"
is implicitly the same as (you can also use -c
instead of -Command
):
powershell -Command .\test.ps1 "foo bar moo"
and that causes PowerShell to evaluate the arguments in two stages:
First, syntactic "
around individual arguments are stripped and the resulting arguments are then joined with spaces to form a single string.
Second, the resulting string - .\test.ps1 foo bar moo
in this case - is then interpreted as PowerShell source code, and, as you can see, the original "
have been stripped by then, resulting in the script receiving 3 arguments.
Note:
-Command
's behavior therefore also involves subjecting the arguments to additional interpretation according to PowerShell's rules, unlike with -File
. E.g.,
powershell -File .\test.ps1 $HOME
would pass $HOME
verbatim to the script, whereas
powershell -Command .\test.ps1 $HOME
would pass the value of PowerShell's automatic $HOME
variable.
With -Command
, passing "
characters that are to become part of the resulting PowerShell code being evaluated indeed requires escaping:
- From PowerShell's perspective, the most robust form is
\"
(sic), though that can result in broken command lines when calling from batch files / cmd.exe
- In cases where that's a problem, pass a single argument enclosed in
"..."
to -Command
, and escape pass-through "
as ""
in PowerShell (Core) / as "^""
(sic) in Windows PowerShell.
See this answer for more guidance on when to use -File
vs. -Command
.
[1] It is understandable to expect -File
, not -Command
to be the default parameter, given that most shell and script-engine CLIs require an explicit parameter (typically, -c
or -e
) to pass a command string rather than a script-file path. Fortunately, in PowerShell (Core) 7+ -File
now is the default, a change that was necessary to support shebang lines on Unix.
Additionally, most shell and script-engine CLIs expect the command string to be passed as a single argument, with any additional arguments then becoming arguments passed to the code in the command string, whereas PowerShell simply stitches multiple arguments together and then interprets the result as the command string; see GitHub issue #4024