[PS] Question about -Recurse

Discussion in 'Scripting' started by Marty List, May 2, 2006.

  1. Marty List

    Marty List Guest

    I'm just curious about the implementation of -Recurse for get-childitem. After
    reading this in the release notes:
    "Parameter binding is changed for "bool" and "SwitchParameter". Previously, the
    full ETS algorithm for conversion to bool was used. That algorithm would accept
    virtually anything and cast it to either true or false. Now, you must specify
    either $true or $false, or an int value (0 is false, everything else is true)."

    I would expect "-Recurse $true" to work. This takes a long time to complete,
    but returns 0 childitems.

    PS H:\> $host.version

    Major Minor Build Revision
    ----- ----- ----- --------
    1 0 9567 0

    PS H:\> gci C:\ -include nsctop.exe -Recurse $true
    PS H:\> gci C:\ -include nsctop.exe -Recurse 1
    PS H:\> gci C:\ -include nsctop.exe -Recurse

    Directory: Microsoft.PowerShell.Core\FileSystem::C:\Program Files\Symantec\
    Symantec System Center

    Mode LastWriteTime Length Name
    ---- ------------- ------ ----
    -a--- 06/23/2005 7:28 PM 910016 NscTop.exe


    PS H:\> gci -?
    <snip>
    -Recurse <System.Management.Automation.SwitchParameter>
    When this parameter is the default state (false) then the current locat
    ion and its first generation (children) are returned. When this paramet
    er is set to true, then all levels, to the end of the tree, are recurse
    d. When the -Recurse parameter is used with the -Name parameter then th
    e item names are returned with their relative path

    Parameter required? false
    Parameter position? named
    Parameter type
    System.Management.Automation.SwitchParameter
    Default value False
    Accept multiple values? false
    Accepts pipeline input? false
    Accepts wildcard characters? false
    </snip>
     
    Marty List, May 2, 2006
    #1
    1. Advertisements

  2. it is changed to a switchParameter :

    -Recurse <System.Management.Automation.SwitchParameter>
    When this parameter is the default state (false) then the current
    location and its first generation (children) are returned. When t
    his parameter is set to true, then all levels, to the end of the
    tree, are recursed. When the -Recurse parameter is used with the -
    Name parameter then the item names are returned with their
    relative path

    gr /\/\o\/\/
     
    /\\/\\o\\/\\/, May 2, 2006
    #2
    1. Advertisements

  3. -recurse is a switchparameter, it's not recommended to provide a value to
    switchparameter, but if you really want to, use ':' as the separator.
    I
    PS C:\monad> gci . a.txt -rec:$false
    PS C:\monad> gci . a.txt -rec:$true


    Directory: Microsoft.PowerShell.Core\FileSystem::C:\monad\select-string


    Mode LastWriteTime Length Name
    ---- ------------- ------ ----
    -a--- 4/18/2006 5:38 PM 35 a.txt


    Directory:
    Microsoft.PowerShell.Core\FileSystem::C:\monad\testdataroot\select-string


    Mode LastWriteTime Length Name
    ---- ------------- ------ ----
    -a--- 4/18/2006 5:38 PM 35 a.txt
     
    Wei Wu [MSFT], May 2, 2006
    #3
  4. Marty List

    Marty List Guest

    You pasted an exact copy of the syntax I posted without adding anything to it?!?
    Am I the only one that doesn't know what a SwitchParameter is? I found this in
    the cmdlet documentation, but it's about as clear as mud:

    1. The Class may include a default parameter set that will be used if a
    disambiguating parameter is not specified.
    2. A parameter of the new SwitchParameter type may be specified. This parameter
    can serve as the disambiguating parameter for rule 1.
    3. If all parameters within a set are optional, then a SwitchParameter is
    required to disambiguate.
    4. If there is more than 1 parameter set and each parameter set has only one
    parameter which can accept input from pipe line, it is recommended to use
    SwitchParameter for the Non default parameter set.


    When I'm writing a "generic purpose" or "keeper" script I prefer to explicitly
    set the value of a parameter, but I guess I can just look up the default value
    and trust that it won't change.

    Is it safe to assume that if a switch parameter is provided then it will
    *always* be the opposite of the default value? So in the case of get-childitem
    if its not present it will always be False, and if it is provided then the value
    will always be True? Or if the default value is True then if its not present it
    will always be True, and if it is provided then the value will always be False?
     
    Marty List, May 3, 2006
    #4
  5. As in other shells, switches are intended to be present or absent. Because
    of the way PowerShell works, we provide special syntax that allows you to
    pass values to switches. There is exactly one scenario for this: passing the
    value of a switch through from a function as shown:

    function mydir ([switch] $recurse, $path) { gci -recurse: $recurse
    $path }

    without this capability, you'd have to write the above as:

    function mydir ([switch] $recurse, $path) {
    if ($recurse)
    {
    dir -recurse $path
    }
    else
    {
    dir $path
    }
    }

    If you want to do this with more than one switch the function becomes
    exponentially more complex. An alternative is to use invoke-expression

    function mydir ([switch]$recurse, $path)
    {
    $cmd = "dir "
    if ($recurse) { $cmd += "-recurse " }
    $cmd += "`$path" # note the backtick on the path variable...
    invoke-expression $cmd
    }

    which scales somewhat better, at the cost of having to construct the code
    and then evaluate it (and we all know the eval is evil!)

    The tcl scripting language has this problem and it always annoyed me. In
    PowerShell we've solved it by providing the special notation for setting
    switches.

    -bruce

    --
    Bruce Payette [MSFT]
    Windows PowerShell Technical Lead
    Microsoft Corporation
    This posting is provided "AS IS" with no warranties, and confers no rights.


     
    Bruce Payette [MSFT], May 3, 2006
    #5
  6. Sorry - we're still working on the documentation...

    In all shell environments, commands typically have 3 kinds of parameters:
    switches which are present or absent like -recurse
    options which take a value like -filter *.cs
    arguments which are positional and take a value like the path for dir

    This is true in cmd.exe, ksh, etc. In the PowerShell lexicon we
    canonicalized things a bit:
    switches == switch parameters
    options == parameters
    arguments == positional parameters

    Arguments are always associated with a parameter name but if that parameter
    is positional, then the name can be left out and it will be inferred from
    position as in:
    dir c:\
    v.s.
    dir -path c:\
    Switch parameters are the opposite - the argument is left out and the value
    is inferred i.e. if the parameter is present or absent.

    dir -recurse c:\

    We use types to control behaviour, so switches are indicated by the type
    SwitchParameter which, for convenience, in scripts can be written as
    [switch]. (We used to use bool for this but co-opting a primitive type for
    this purpose was problematic.)

    Since the value of a switch is highly constrained, initializing them is not
    necessary or recommended:

    PS (1) > function get-soup (
    PS (2) > get-soup
    No soup for you!
    PS (3) > get-soup -please
    Here's your chicken noodle soup
    PS (4) > get-soup -please tomato
    Here's your tomato soup
    PS (5) >

    Note: you should *never* have a function, script or cmdlet where a switch
    parameter defaults to true. They should always default to false and then are
    set to true if present.

    -bruce
     
    Bruce Payette [MSFT], May 3, 2006
    #6
  7. Marty List

    Marty List Guest

    Thanks Bruce, good explanation. Make sure this part gets added to the
    documentation (unless its already there & I missed it)

    "you should *never* have a function, script or cmdlet where a switch
    parameter defaults to true. They should always default to false and then are
    set to true if present."


     
    Marty List, May 3, 2006
    #7
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.