2

I have a command similar to the following that I need to run as part of a PowerShell script:

gfpca -run.config default.conf

However, I receive the error Command not found: .conf on the output. This happens if I run with Invoke-Expression as well. I have also tried escaping the character, but don't see a difference:

Invoke-Expression('gfpca -run`.config default.conf')

How can I run this command within PowerShell?

phuclv
  • 37,963
  • 15
  • 156
  • 475

2 Answers2

2

Use the & invocation operator to invoke the program and use regular ' single-quotes to qualify the argument boundaries:

& gfpca '-run.config' 'default.conf'

Now, PowerShell will pass -run.config and default.conf to gfpca as-is without attempting to interpret them as native parameters

Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
2

tl;dr

Due to an unfortunate bug, still present as of this writing (PowerShell 7.3.4), an argument passed to an external program that starts with - and contains . requires escaping or quoting, which in the simplest case means:

# Note the ` before -
gfpca `-run.config default.conf

To be clear: This shouldn't be necessary.


Mathias R. Jessen's answer provides an effective solution, but let me add some context:

  • You only need to escape or quote one of your arguments, -run.config, due to a PowerShell bug, where passing an unquoted argument that starts with - and contains a . to an external program is mistakenly passed as two arguments.

    • In other words: Without escaping or quoting such an argument (see below), PowerShell mistakenly passes -run.config as separate arguments -run and .config

    • The bug, still present as of this writing (PowerShell 7.3.4), has been reported in GitHub issue #6291, where it was acknowledged as such, but is awaiting a fix; it is one of several bugs relating to --prefixed tokens.

  • While using &, the call operator, unconditionally for command invocations is a robust approach, it is important to note that it is only necessary if the command name or path is quoted and/or contains variable references - which isn't the case here.

  • Invoke-Expression (iex) should generally be avoided - see this answer. Specifically, do not use it to invoke an external program or PowerShell script - see this answer.

    • As an aside: Your call, InvokeExpression('...'), uses pseudo method syntax, which is to be avoided: PowerShell functions, cmdlets, scripts, and external programs must be invoked like shell commands - Invoke-Expression '...' - not like C# methods. That is, don't put ((...) around the argument list, and separate argument with whitespace, not with ,. See this answer for more information.

While ` (PowerShell's escape character), which you tried to use, is (a) key to the solution, it must be applied to the initial -, which prevents PowerShell from (inappropriately) parsing the argument according to the rules of PowerShell-native parameter names.[1]

# Note the ` before - 
gfpca `-run.config default.conf

As shown in Mathias' answer, using a quoted string around the whole argument (e.g. '-run.config') is an alternative.


[1] Because parameter names aren't expected to require escaping, what follows - is parsed verbatim, up to the first .. Therefore, your attempt to `-escape the . character was ineffective: ` wasn't recognized as an escape character and therefore retained, and the bug still kicked in. By contrast, `-escaping the initial - prevents PowerShell from parsing the entire token as a parameter, which bypasses the bug

mklement0
  • 382,024
  • 64
  • 607
  • 775