Skip to content

Hashtable-based splatting produces unhelpful arguments / command line for external programs #9343

@mklement0

Description

@mklement0

While not common, it is possible to use hashtable-based splatting for passing arguments to external programs.

Unfortunately, PowerShell chooses to represent a parameter-name-argument pair as a single token with : as the separator.

E.g., using hashtable $ht = @{ foo = 'bar' } for splatting (as @ht) produces single argument
-foo:bar.

To my knowledge it is uncommon for external CLIs to support this syntax.

By far the most common syntax is to separate the parameter name from its value with a space (effectively passing the parameter value as a separate argument: -foo bar, as is typically used even in PowerShell itself.

Note that Boolean entries in the hashtable would need special consideration: under the sensible assumption that they represent the equivalent of switch parameters in PowerShell, i..e, to options in POSIX parlance (e.g., grep's -o option) :

  • a value of $true would have to result in the key name by itself; i.e., an entry of o = $true would result in -o

  • a value of $false would have to result in the omission of the entry.

Technically, this would be a breaking change.
If not an option, it is a candidate for #6745.

Note that per POSIX only single-character parameter names are allowed; while the GNU utilities on Linux distros do support multi-character names, they require -- rather than - as the sigil (e.g., --only-matching as the alias of -o with grep); therefore, use of the long option names wouldn't work with the above proposal.

Steps to reproduce

Run the following Pester test on macOS or Linux (the behavior would be the same on Windows, but bash is used to echo the arguments passed).

Describe "Hash-table based splatting with external programs"  {
  It "Parameter names and their arguments should be separated with spaces" -Skip:$IsWindows {
      $htArgs = @{
        foo = 'bar'
      }
      bash -c 'echo \"$@\"' - @htArgs | Should -Be '-foo bar'
  }
}

Expected behavior

If spaces were used, the test would pass.

Actual behavior

The test fails:

     Expected: '-foo bar'
     But was:  '-foo:bar'

Environment data

PowerShell Core 6.2.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue-Questionideally support can be provided via other mechanisms, but sometimes folks do open an issue to get aResolution-No ActivityIssue has had no activity for 6 months or moreWG-Enginecore PowerShell engine, interpreter, and runtime

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions