Search code examples
powershellfilterfile-extensionget-childitemwrite-host

Powershell Get Child Item Exclude doesn't work in current directory


As I mentioned in question, this seems like bug in Powershell engine.

When I try to print the files in the current directory(where the said powershell script is also present) by excluding some file-types(extensions), it doesn't print anything. For eg. below codes print contents of Current Folder in the Powershell console:

gci
gci -pa .

Both the above codes print the directory contents as below:

Mode                LastWriteTime         Length Name                                                                                     
----                -------------         ------ ----                                                                                     
-a----       20-09-2020     22:37      835799796 file1.mkv                                                                      
-a----       20-09-2020     22:25            148 file1.srt                                      
-a----       23-09-2020     04:53            357 scriptv1.ps1                                                           
-a----       20-09-2020     22:25            678 file1.txt

But when I run below code, it doesn't print anything, when it must print file1.txt:

$excluded = @('*.mkv','*.mp4','*.srt','*.sub','*.ps1')
Get-ChildItem -Exclude $excluded | Write-Host { $_.FullName }

Can anyone assist figuring out why is it happening and how to get what I mentioned ?


Solution

  • The use of -Exclude with Get-ChildItem is not intuitive. To get consistent results with Get-ChildItem, you must qualify your path with \* or use the -Recurse switch. If you do not care to recurse, you can just use Get-Item with a \* qualifying the path.

    # Works but includes all subdirectory searches
    Get-ChildItem -Path .\* -Exclude $excluded
    Get-ChildItem -Path .\* -Exclude $excluded -File
    Get-ChildItem -Path . -Exclude $excluded -File -Recurse
    
    # Best results for one directory
    Get-Item -Path .\* -Exclude $excluded
    

    The reason recursion should be used is because -Exclude values are applied to the leaf of -Path value first. If any of those exclusions match your target directory, then it will be excluded and prevent any of its items from being displayed. See below:

    $path = 'c:\temp'
    # produces nothing because t* matches temp
    Get-ChildItem -Path $path -Exclude 't*'