How can I exclude multiple folders using Get-ChildItem -exclude?

前端 未结 12 785
星月不相逢
星月不相逢 2020-11-27 16:19

I need to generate a configuration file for our Pro/Engineer CAD system. I need a recursive list of the folders from a particular drive on our server. However I need to EXCL

相关标签:
12条回答
  • 2020-11-27 16:50

    I wanted a solution that didn't involve looping over every single item and doing ifs. Here's a solution that is just a simple recursive function over Get-ChildItem. We just loop and recurse over directories.

    
    function Get-RecurseItem {
        [Cmdletbinding()]
        param (
            [Parameter(ValueFromPipeline=$true)][string]$Path,
            [string[]]$Exclude = @(),
            [string]$Include = '*'
        )
        Get-ChildItem -Path (Join-Path $Path '*') -Exclude $Exclude -Directory | ForEach-Object {
            @(Get-ChildItem -Path (Join-Path $_ '*') -Include $Include -Exclude $Exclude -File) + ``
            @(Get-RecurseItem -Path $_ -Include $Include -Exclude $Exclude)
        }
    }
    
    0 讨论(0)
  • 2020-11-27 16:51

    I'd do it like this:

    Get-ChildItem -Path $folder -r  | 
              ? { $_.PsIsContainer -and $_.FullName -notmatch 'archive' }
    
    0 讨论(0)
  • 2020-11-27 16:52

    Based on @NN_ comment on @Guillem answer, I came up with the below code. This allows you to exclude folders and files:

    Get-ChildItem -Exclude 'folder-to-exclude','second-folder-exclude' |
    foreach {
        Get-ChildItem -Path $_ -Exclude 'files-to-exclude','*.zip','*.mdmp','*.out*','*.log' -Recurse |
        Select-String -Pattern 'string-to-look-for' -List
    }
    
    0 讨论(0)
  • 2020-11-27 16:53

    I apologize if this answer seems like duplication of previous answers. I just wanted to show an updated (tested through POSH 5.0) way of solving this. The previous answers were pre-3.0 and not as efficient as modern solutions.

    The documentation isn't clear on this, but Get-ChildItem -Recurse -Exclude only matches exclusion on the leaf (Split-Path $_.FullName -Leaf), not the parent path (Split-Path $_.FullName -Parent). Matching the exclusion will just remove the item with the matching leaf; Get-ChildItem will still recurse into that leaf.

    In POSH 1.0 or 2.0

    Get-ChildItem -Path $folder -Recurse  | 
              ? { $_.PsIsContainer -and $_.FullName -inotmatch 'archive' }
    

    Note: Same answer as @CB.

    In POSH 3.0+

    Get-ChildItem -Path $folder -Directory -Recurse  | 
              ? { $_.FullName -inotmatch 'archive' }
    

    Note: Updated answer from @CB.

    Multiple Excludes

    This specifically targets directories while excluding leafs with the Exclude parameter, and parents with the ilike (case-insensitive like) comparison:

    #Requires -Version 3.0
    [string[]]$Paths = @('C:\Temp', 'D:\Temp')
    [string[]]$Excludes = @('*archive*', '*Archive*', '*ARCHIVE*', '*archival*')
    
    $files = Get-ChildItem $Paths -Directory -Recurse -Exclude $Excludes | %{ 
        $allowed = $true
        foreach ($exclude in $Excludes) { 
            if ((Split-Path $_.FullName -Parent) -ilike $exclude) { 
                $allowed = $false
                break
            }
        }
        if ($allowed) {
            $_
        }
    }
    

    Note: If you want your $Excludes to be case-sensitive, there are two steps:

    1. Remove the Exclude parameter from Get-ChildItem.
    2. Change the first if condition to:
      • if ($_.FullName -clike $exclude) {

    Note: This code has redundancy that I would never implement in production. You should simplify this quite a bit to fit your exact needs. It serves well as a verbose example.

    0 讨论(0)
  • 2020-11-27 16:54

    You can exclude like this, the regex 'or' symbol, assuming a file you want doesn't have the same name as a folder you're excluding.

    $exclude = 'dir1|dir2|dir3'
    ls -r | where { $_.fullname -notmatch $exclude }
    
    ls -r -dir | where fullname -notmatch 'dir1|dir2|dir3'
    
    0 讨论(0)
  • 2020-11-27 16:54

    VertigoRay, in his answer, explained that -Exclude works only at the leaf level of a path (for a file the filename with path stripped out; for a sub-directory the directory name with path stripped out). So it looks like -Exclude cannot be used to specify a directory (eg "bin") and exclude all the files and sub-directories within that directory.

    Here's a function to exclude files and sub-directories of one or more directories (I know this is not directly answering the question but I thought it might be useful in getting around the limitations of -Exclude):

    $rootFolderPath = 'C:\Temp\Test'
    $excludeDirectories = ("bin", "obj");
    
    function Exclude-Directories
    {
        process
        {
            $allowThrough = $true
            foreach ($directoryToExclude in $excludeDirectories)
            {
                $directoryText = "*\" + $directoryToExclude
                $childText = "*\" + $directoryToExclude + "\*"
                if (($_.FullName -Like $directoryText -And $_.PsIsContainer) `
                    -Or $_.FullName -Like $childText)
                {
                    $allowThrough = $false
                    break
                }
            }
            if ($allowThrough)
            {
                return $_
            }
        }
    }
    
    Clear-Host
    
    Get-ChildItem $rootFolderPath -Recurse `
        | Exclude-Directories
    

    For a directory tree:

    C:\Temp\Test\
    |
    ├╴SomeFolder\
    |  |
    |  └╴bin (file without extension)
    |
    └╴MyApplication\
      |
      ├╴BinFile.txt
      ├╴FileA.txt
      ├╴FileB.txt
      |
      └╴bin\
        |
        └╴Debug\
          |
          └╴SomeFile.txt
    

    The result is:

    C:\Temp\Test\
    |
    ├╴SomeFolder\
    |  |
    |  └╴bin (file without extension)
    |
    └╴MyApplication\
      |
      ├╴BinFile.txt
      ├╴FileA.txt
      └╴FileB.txt
    

    It excludes the bin\ sub-folder and all its contents but does not exclude files Bin.txt or bin (file named "bin" without an extension).

    0 讨论(0)
提交回复
热议问题