list 如何使用 Get-ChildItem -exclude 排除多个文件夹?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15294836/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 01:58:25  来源:igfitidea点击:

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

listpowershelldirectory

提问by peterjfrancis

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 EXCLUDE any folder with 'ARCHIVE' in it including the various different cases.

我需要为我们的 Pro/Engineer CAD 系统生成一个配置文件。我需要来自我们服务器上特定驱动器的文件夹的递归列表。但是,我需要排除任何包含“ARCHIVE”的文件夹,包括各种不同的情况。

I've written the following which works except it doesn't exclude the folders !!

我写了以下内容,但不排除文件夹!

$folder = "T:\Drawings\Design\*"
$raw_txt = "T:\Design Projects\Design_Admin\PowerShell\raw.txt"
$search_pro = "T:\Design Projects\Design_Admin\PowerShell\search.pro"
$archive = *archive*,*Archive*,*ARCHIVE*

Get-ChildItem -Path $folder -Exclude $archive -Recurse  | where {$_.Attributes -match 'Directory'}  | ForEach-Object {$_.FullName} > $search_pro   

回答by guillem

My KISSapproach to skip some folders is chaining Get-ChildItemcalls. This excludes root level folders but not deeper level folders if that is what you want.

我跳过某些文件夹的KISS方法是链接Get-ChildItem调用。如果这是您想要的,这不包括根级别文件夹,但不包括更深级别的文件夹。

Get-ChildItem -Exclude folder1,folder2 | Get-ChildItem -Recurse | ...
  • Start excludingfolders you don't want
  • Then do the recursivesearch with non desired folders excluded.
  • 开始排除您不想要的文件夹
  • 然后在排除不需要的文件夹的情况下进行递归搜索。

What I like from this approach is that it is simple and easy to remember. If you don't want to mix folders and files in the first search a filter would be needed.

我喜欢这种方法的一点是它简单易记。如果您不想在第一次搜索中混合文件夹和文件,则需要一个过滤器。

回答by CB.

I'd do it like this:

我会这样做:

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

回答by VertigoRay

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.

如果这个答案看起来与以前的答案重复,我深表歉意。我只是想展示一个更新的(通过 POSH 5.0 测试)解决这个问题的方法。以前的答案是 3.0 之前的,不如现代解决方案有效。

The documentationisn't clear on this, but Get-ChildItem -Recurse -Excludeonly 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-ChildItemwill still recurse into that leaf.

文档对此并不清楚,但Get-ChildItem -Recurse -Exclude仅匹配叶 ( Split-Path $_.FullName -Leaf)上的排除,而不匹配父路径 ( Split-Path $_.FullName -Parent)。匹配排除只会删除具有匹配叶子的项目;Get-ChildItem仍然会递归到那片叶子。

In POSH 1.0 or 2.0

在 POSH 1.0 或 2.0

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

Note:Same answer as @CB.

注意:@CB相同的答案

In POSH 3.0+

在 POSH 3.0+

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

Note:Updated answer from @CB.

注意:来自@CB 的更新答案

Multiple Excludes

多项排除

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

这专门针对目录,同时排除带有Exclude参数的叶子,以及带有ilike(不区分大小写的)比较的父目录:

#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 $Excludesto be case-sensitive, there are two steps:

注意:如果您希望$Excludes区分大小写,有两个步骤:

  1. Remove the Excludeparameter from Get-ChildItem.
  2. Change the first ifcondition to:
    • if ($_.FullName -clike $exclude) {
  1. 从 中删除Exclude参数Get-ChildItem
  2. 将第一个if条件更改为:
    • 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.

注意:此代码具有我永远不会在生产中实现的冗余。您应该稍微简化一下以适应您的确切需求。它可以很好地作为一个详细的例子。

回答by alroc

The exclusion pattern shouldbe case-insensitive, so you shouldn't have to specify every case for the exclusion.

排除模式应该不区分大小写,因此您不必为排除指定每种情况。

That said, the -Excludeparameter accepts an array of strings, so as long as you define $archiveas such, you should be set.

也就是说,-Exclude参数接受一个字符串数组,所以只要你这样定义$archive,你就应该被设置。

$archive = ("*archive*","*Archive*","*ARCHIVE*");

$archive = ("*archive*","*Archive*","*ARCHIVE*");

You also should drop the trailing asterisk from $folder- since you're specifying -recurse, you should only need to give the top-level folder.

您还应该删除结尾的星号$folder- 因为您指定的是-recurse,所以您只需要提供顶级文件夹。

$folder = "T:\Drawings\Design\"

$folder = "T:\Drawings\Design\"

Fully revised script. This also changes how you detect whether you've found a directory, and skips the Foreach-Objectbecause you can just pull the property directly & dump it all to the file.

完全修改的脚本。这也会改变您检测是否找到目录的方式,并跳过 ,Foreach-Object因为您可以直接提取属性并将其全部转储到文件中。

$folder = "T:\Drawings\Design\";
$raw_txt = "T:\Design Projects\Design_Admin\PowerShell\raw.txt";
$search_pro = "T:\Design Projects\Design_Admin\PowerShell\search.pro";
$archive = ("*archive*","*Archive*","*ARCHIVE*");

Get-ChildItem -Path $folder -Exclude $archive -Recurse  | where {$_.PSIsContainer}  | select-Object -expandproperty FullName |out-file $search_pro 

回答by lil

I know this is quite old - but searching for an easy solution, I stumbled over this thread... If I got the question right, you were looking for a way to list more than one directory using Get-ChildItem. There seems to be a much easier way using powershell 5.0 - example

我知道这已经很老了 - 但是在寻找一个简单的解决方案时,我偶然发现了这个线程......如果我的问题是对的,那么您正在寻找一种使用 Get-ChildItem 列出多个目录的方法。使用 powershell 5.0 似乎有更简单的方法 - 示例

Get-ChildItem -Path D:\ -Directory -Name -Exclude tmp,music
   chaos
   docs
   downloads
   games
   pics
   videos

Without the -Exclude clause, tmp and music would still be in that list. If you don't use -Name the -Exclude clause won't work, because of the detailed output of Get-ChildItem. Hope this helps some people that are looking for an easy way to list all directory names without certain ones...

如果没有 -Exclude 子句,tmp 和 music 仍将在该列表中。如果您不使用 -Name,则 -Exclude 子句将不起作用,因为 Get-ChildItem 的详细输出。希望这可以帮助一些正在寻找一种简单的方法来列出所有目录名称而没有某些目录名称的人......

Cheers lil

干杯律

回答by Simon Tewsi

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.

VertigoRay 在他的回答中解释说 -Exclude 仅适用于路径的叶级(对于文件,路径被删除的文件名;对于子目录,路径被删除的目录名)。所以看起来 -Exclude 不能用于指定目录(例如“bin”)并排除该目录中的所有文件和子目录。

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):

这是一个排除一个或多个目录的文件和子目录的函数(我知道这不是直接回答问题,但我认为它可能有助于解决 -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).

它排除 bin\ 子文件夹及其所有内容,但不排除文件 Bin.txt 或 bin(名为“bin”的文件,没有扩展名)。

回答by js2010

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'

回答by Nathan Goings

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

基于对@Guillem 答案的@NN_ 评论,我想出了以下代码。这允许您排除文件夹和文件:

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
}

回答by Jason Brower

#For brevity, I didn't define a function.

#Place the directories you want to exclude in this array.
#Case insensitive and exact match. So 'archive' and
#'ArcHive' will match but 'BuildArchive' will not.
$noDirs = @('archive')

#Build a regex using array of excludes
$excRgx = '^{0}$' -f ($noDirs -join ('$|^'))

#Rather than use the gci -Recurse option, use a more
#performant approach by not processing the match(s) as
#soon as they are located.
$cmd = {
  Param([string]$Path)
  Get-ChildItem $Path -Directory |
  ForEach-Object {
    if ($_.Name -inotmatch $excRgx) {
      #Recurse back into the scriptblock
      Invoke-Command $cmd -ArgumentList $_.FullName;
      #If you want all directory info change to return $_
      return $_.FullName
    }
  }
}

#In this example, start with the current directory
$searchPath = .
#Start the Recursion
Invoke-Command $cmd -ArgumentList $searchPath

回答by Luiz Felipe

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.

我想要一个不涉及遍历每个项目并执行ifs的解决方案。这是一个解决方案,它只是一个简单的递归函数Get-ChildItem。我们只是循环和递归目录。


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)
    }
}