Search notes:

PowerShell: Arrays as arguments to executables and PowerShell scripts

This page tries to summarize my investigations on the particularities when invoking PowerShell scripts and executables with arrays as their arguments.

PowerShell script and executable

First, we need a PowerShell script and an executable that prints the number of arguments received and the value of each of these arguments.

ShowArgs.ps1

ShowArgs.ps1 is the PowerShell script which basically iterates over $args and prints its values and types.
write-host "ShowArgs.ps1: argument count is $($args.length)"
$args | foreach-object { "  $_  ($($_.GetType().FullName))" }

ShowArgs.exe

ShowArgs.exe is the corresponding executable. It is created from the following C# source file:
using System;
public class ShowArgs {

  static void Main(String[] argv) {
     Console.WriteLine($"ShowArgs.exe: argument count is {argv.Length}:");
     foreach (var arg in argv) {
        Console.WriteLine("  " + arg);
     }
  }
}
The compilation into an executable with the csc compiler is simple:
csc ShowArgs.cs
Unlike ShowArgs.ps1, ShowArgs.exe does not print the types of the arguements because they're constraint to strings.

Some tests

With the script and the exe, we're ready for some test

foo, bar, baz

In PowerShell, the comma in an expression like foo, bar, baz acts as a comma operator which creates an array.
Thus, the PowerShell script receives one argument which is the array that was passed to the script:
PS C:\users\rene> .\ShowArgs.ps1 foo, bar, baz
ShowArgs.ps1: argument count is 1
  foo bar baz  (System.Object[])
An executable on the other hand receives three elements rather than one array:
PS C:\users\rene> .\ShowArgs.exe: argument count is 3:
  foo
  bar
  baz

foo,bar,baz

On a syntactic level, foo,bar,baz is the same array as foo, bar, baz and thus is processed equaly when passed to the PowerShell script:
PS C:\users\rene> .\ShowArgs.ps1 foo,bar,baz
ShowArgs.ps1: argument count is 1
  foo bar baz  (System.Object[])
Interestingly, the executable now receives one argument. Thus, the space is important when calling executables:
PS C:\users\rene> .\ShowArgs.exe foo,bar,baz
ShowArgs.exe: argument count is 1:
  foo,bar,baz

foo,bar baz

foo,bar baz consists of an array (with the elements foo and bar) and the token baz. Thus, the PowerShell scripts receives an array and a string:
PS C:\users\rene> .\ShowArgs.ps1 foo,bar baz
ShowArgs.ps1: argument count is 2
  foo bar  (System.Object[])
  baz  (System.String)
The executable also receives two arguments, which agrees with the previous observation that spaces are important when calling executables.
PS C:\users\rene> .\ShowArgs.exe foo,bar baz
ShowArgs.exe: argument count is 2:
  foo,bar
  baz

Emulating xargs

Because the elements of an array that is passed to an executable are assigned to individual arguments, it is possible to emulate xargs in PowerShell with a construct like this:
.\prog.exe (get-childItem -recurse -filter *.txt)

Index