Excluding multiple folders from Get-ChildItem

This topic contains 4 replies, has 3 voices, and was last updated by Profile photo of Curtis Smith Curtis Smith 8 months ago.

  • Author
    Posts
  • #37545
    Profile photo of Tommy Gunz
    Tommy Gunz
    Participant

    Hi,

    I have the below code, which finds all .doc and .csv files in my C:\ except in the 'Program Files' folder and all of it's sub folders (i'm assuming). This code works:


    $source="c:\" #location of starting directory
    $files=@("*.doc", "*.csv")

    Get-ChildItem -recurse ($source) -include ($files) | Where-Object {$_.PSParentPath -notlike "*Program Files*" -and !$_.PSISContainer}

    I would like to now exclude multiple folders and all their sub-folders / files from being searched, like the 'Users' & 'Windows' folders, how would I do this???

    Many Thanks,

  • #37547
    Profile photo of Richard Diphoorn
    Richard Diphoorn
    Participant

    Can't remember where I have this code from, but I think it will work for you. It searches directories. It will put the results in variable $files:

    #requires -Version 3
    [string[]]$paths = @('C:\')
    [string[]]$excludes = @('*Program Files*','*Windows*')
    
    $files = Get-ChildItem -Path $paths -Directory -Recurse -Exclude $excludes | ForEach-Object -Process { 
      
      $allowed = $true
      
      foreach ($exclude in $excludes) { 
        
        if ((Split-Path -Path $_.FullName -Parent) -ilike $exclude) { 
          
          $allowed = $false
          
          break
        
        }
      
      }
      
      if ($allowed) {
        $_
      }
    
    }
    
  • #37550
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    You can just add to your existing Where-Object filter.

    ***Note I also removed the !$_.PSISContainer from Where-Object and used the -File parameter of Get-ChildItem instead. It makes the Where-Object more readable and the Get-ChildItem statement more efficient***

    $source="c:\" #location of starting directory
    $files=@("*.doc", "*.csv")
    
    Get-ChildItem -recurse ($source) -include ($files) -File | Where-Object {$_.PSParentPath -notlike "*Program Files*" -and $_.PSParentPath -notlike "*Users*" -and $_.PSParentPath -notlike "*Windows*"}
    

    Additionally, if you are proficient with Regular Expression, you can use -notmatch instead of -notlike to trim some of the redundancy off.

    $source="c:\" #location of starting directory
    $files=@("*.doc", "*.csv")
    
    Get-ChildItem -recurse ($source) -include ($files) -File | Where-Object {$_.PSParentPath -notmatch "Program Files|Users|Windows"}
    
  • #37556
    Profile photo of Tommy Gunz
    Tommy Gunz
    Participant

    Thank you both for your suggestions.

    Curtis when I run your code, it runs, but it still looks like it searches C:\Windows\ because I get the below error message:

    Get-ChildItem : Access to the path 'C:\Windows\CSC' is denied.

    Get-ChildItem : Access to the path 'C:\Windows\System32\LogFiles\WMI\RtBackup' is denied.

    Am i missing something??

    MAny Thanks

  • #37560
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    It's because the filtering is happening further down the pipeline. There is nothing at the Get-ChildItem cmdlet to tell it to not look in the Windows directory. What is happening is this.

    1) Get-ChildItem is doing a recursive search from the root of C:\ and filtering to include only files that end in .doc and .csv. It will go into every folder it can and output the results of those files to the pipeline.
    2) Where-Object takes those results and looks to see if any of them are in the defined directories "Program Files|Users|Windows". If so, it removes them from the pipeline. So all that are left are the ones that are not in those directories.

    So yes, Get-ChildItem is still looking in the Windows directory, because there is not a way to tell it not to; but the results are filtered so that you only get the data you want.

You must be logged in to reply to this topic.