如何在排除其他人的同时过滤Powershell中的包含文件夹

How to filter include folders in Powershell while excluding others

我想过滤包含特定条件的文件夹列表,同时排除 PowerShell 中的另一组条件。

下面的代码是目前正在玩的部分继承的代码; -Exclude 似乎排除了名称中包含 *EDS* 但不包含 *eng* 的文件夹。以下是仍包含的内容的示例输出:

C:\Users\USERNAME\Box\CTRL Active Projects\project1\project1_OPS-Software-Database Backups-Record Backup
C:\Users\USERNAME\Box\CTRL Active Projects\project1\project1_OPS-Software-Database Backups
C:\Users\USERNAME\Box\CTRL Active Projects\project1\project1_OPS-Eng-Submittals WIP\Backups

-Exclude *eng*, *EDS* 最终可能会转换为 variable/named 数组列表。

# Find sub-folder within job folder
$DatabaseFolder = (Get-ChildItem -Path $JobFolder -Filter "*Backup*" -Exclude *eng*, *EDS* -Recurse -Directory).Fullname | Sort-Object -Descending -Property LastWriteTime
Write-Output $DatabaseFolder

$JobFolderreturns搜索子目录的路径:

C:\Users\USERNAME\Box\CTRL Active Projects\project1\

一些其他背景信息:PowerShell 5.1 正在用作管理员,Windows 10 OS

有人能帮我理解为什么代码仍然包含一些排除的参数吗?

我在文档中没有看到任何关于使用过滤和排除的信息:

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-childitem?view=powershell-7.2

但是,由于它没有按预期工作,您始终可以手动执行排除:

gci -recurse -directory | ? { $_.Name -notlike "*eng*" -and $_.Name -notlike "*EDS*" }
  • -Filter-Include / -Exclude 仅在 last 路径组件上运行 - 即输入file-system 项目的 名称 (.Name 属性).

  • -Exclude-Recurse合并时,只排除匹配项自身不排除他们的子树。也就是说,排除目录的 contents(子项)仍会被枚举(除非它们的名称也恰好与排除模式匹配)。

因此,例如,...-Eng-Submittals WIP\Backups 仍包含在您的输出中:*eng* -Exclude 过滤器排除了 ...-Eng 本身,但继续枚举其 子目录.

从 PowerShell (Core) 7.2.1 开始,有 no 直接方法通过 subtrees 通配符模式从 Get-ChildItem -Recurse枚举; GitHub issue #15159 建议添加此功能。


因此,您必须通过 post 执行排除 - 使用与 匹配的 Where-Object 调用进行过滤完整路径 (.FullName 属性):

Get-ChildItem -Recurse -Directory -Path $JobFolder -Filter *Backup* |
  Where-Object FullName -notmatch 'eng|EDS'

注意:为简洁起见,-notmatch 和使用交替 (|) 的 regex 用于匹配多个子字符串。

要使用上面显示的wildcard expressions, you'd have to use the -notlike operator multiple times, once for each pattern (which would also require you to use a script block argument, with explicit use of $_, i.e. you then couldn't use the simplified syntax;换句话说:
Where-Object { $_.FullName -notlike '*eng*' -and $_.FullName -notlike '*EDS*' }).