Last Updated: February 25, 2016
·
1.873K
· mdonoughe

Taking input from Get-ChildItem

This may or may not be obvious, but I had to figure this out by finding the .Net class for a cmdlet that implements this behavior and inspecting the attributes.

When creating a cmdlet that acts on files, it would be nice to have syntax like ls c:\ | test. Unfortunately, the simplest script will not work:

[CmdletBinding()]
param([Parameter(Position = 0, Mandatory = $True, ValueFromPipeline = $True)][string[]]$Path)

process
{
  Get-Item $Path
}

PS C:\temp> ls c:\ | test
Get-Item : Cannot find path 'C:\temp\adt-bundle-windows' because it does not exist.

PowerShell is converting the FileInfo objects from Get-ChildItem into strings, as requested, but it's doing by giving you the file name without the path.

What you need to do is get the value of the PSPath property from the pipeline input objects and pass that into Get-Item -LiteralPath like this:

[CmdletBinding(DefaultParameterSetName = 'Path')]
param([Parameter(Position = 0, ParameterSetName = 'Path', Mandatory = $True, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)][string[]]$Path,
      [Parameter(ParameterSetName = 'LiteralPath', Mandatory = $True, ValueFromPipeline = $False, ValueFromPipelineByPropertyName = $True)][Alias('PSPath')][string[]]$LiteralPath)

process
{
  if ($PSCmdlet.ParameterSetName -eq 'Path')
  {
    Get-Item $Path
  }
  else
  {
    Get-Item -LiteralPath $LiteralPath
  }
}

PS C:\temp> ls c:\ | test


    Directory: C:\


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        2012-12-08   4:19 PM            adt-bundle-windows

The parameter sets are necessary if you want to support -LiteralPath and "normal" paths with wildcards. The important part that makes this work with Get-ChildItem is the alias for PSPath on the LiteralPath parameter. You could just name your parameter PSPath, but LiteralPath is more standard and descriptive.