Search code examples
powershellget-childitem

Dynamically created parameter arguments for PowerShell's Get-ChildItem


Long story short, I'm trying to dynamically use a parameter -Directory or -File in PowerShell's Get-ChildItem. Guess what? I'm unable to.

Here's the deal (note: pseudo-code):

Param(
    [string]$filter = $(throw "Error: name"),
    [string]$type = $(throw "error: file or directory")
)

if( $type -eq "file" ) {
    $mode = '-File'
}
elseif( $type -eq "directory" ) {
    $mode = '-Directory'
}

Function Find_Plugin_folder {
    Write-Host "look for: '$($filter)'"
    Invoke-Command -ComputerName (Get-Content servers.txt ) -ScriptBlock {
        (Get-ChildItem -Path "z:\www" -Depth 5 $Using:mode -Filter $Using:filter -Recurse ) | %{$_.FullName}
    } -ThrottleLimit 80 
}

Find_Plugin_folder

$Using:mode is where it throws an error, either:

PS C:\Users\janreilink> v:\test.ps1 vevida-optimizer file
look for: 'vevida-optimizer'
A positional parameter cannot be found that accepts argument '-File'.
    + CategoryInfo          : InvalidArgument: (:) [Get-ChildItem], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
    + PSComputerName        : webserver-01.example.net

Or

PS C:\Users\janreilink> v:\test.ps1 vevida-optimizer directory
look for: 'vevida-optimizer'
A positional parameter cannot be found that accepts argument '-Directory'.
    + CategoryInfo          : InvalidArgument: (:) [Get-ChildItem], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
    + PSComputerName        : webserver-01.example.net

I've been reading about Dynamic Parameter sets all afternoon, but can't wrap my head around it yet. Any points are much (much, much) appreciated.


Solution

  • You'll want to use splatting for this instead. Start by creating a hashtable with some or all of the parameters you want to pass:

    $dynamicArgs = @{}
    
    if( $type -eq "file" ) {
        $dynamicArgs['File'] = $true
    }
    elseif( $type -eq "directory" ) {
        $dynamicArgs['Directory'] = $true
    }
    

    Then, inside Invoke-Command, prefix the variable name with @ to indicate that you want to "splat" the arguments:

    Get-ChildItem -Path "z:\www" -Depth 5 @Using:dynamicArgs -Filter $Using:filter -Recurse
    

    If the splatting table contains the key File with a value of $true, it's the equivalent of adding -File:$true on the command line, and vice versa for the Directory argument