Search code examples
powershell

Unexpected Get-ChildItem -recurse results


Can anyone explain this output when using the Get-ChildItem cmdlet to list files in a folder that doesn't exist? For example:

Get-ChildItem -Path "c:\nonexisitantfolder" -recurse

I assumed that it would start in the given path and fail immediately as the path doesn't exist. Instead it seems to scan the whole drive (or at least I'm guessing this is what's happening as it outputs occasional access denied messages for unrelated folders) then eventual fails. It's almost as it when the absolute path can't be found - and surely this is definitely an absolute path in the Windows world - it starts looking for it as a relative subfolder path?

Note: I'm not trying to list files in a nonexisitant directory, I stumbled across this unlikely behaviour when testing how a script would respond to being given a false directory name as input.


Solution

  • tl;dr

    To avoid the problematic behavior, use -LiteralPath rather than -Path

    # Fails, if the target path doesn't exist, thanks to `-LiteralPath`
    Get-ChildItem -LiteralPath "c:\nonexistentfolder" -Recurse
    

    Get-ChildItem's -Path parameter by design treats a given path as a wildcard expression.
    Also note that if you don't specify -Path explicitly before the path argument, it is positionally implied.

    The unexpected part is that when combined with -Recurse, the last component of a path bound to -Path is unexpectedly looked for on every level of the parent path's directory subtree - even if that last component doesn't contain actual wildcard metacharacters such as * and ?.

    That is, Get-ChildItem -Path "C:\nonexistentfolder" -Recurse looks for files and folders named nonexistentfolder on every level of the directory subtree of C:\.

    This problematic and potentially destructive behavior is the subject of GitHub issue #5699.

    By contrast, -LiteralPath by design treats its arguments literally and uses them as-is.