【问题标题】:Exclude multiple subfolders while using Powershell's method Get-Childitem使用 Powershell 的方法 Get-Childitem 时排除多个子文件夹
【发布时间】:2013-11-19 11:42:37
【问题描述】:

我有什么

以下工作代码列出了放置脚本的所有子文件夹中的所有文件。
它仅包括某些文件类型,并排除某个文件夹中的所有文件。到目前为止一切顺利

$fileInclude = @("*.txt", "*.hgr", "*.dat")           
$folderExclude = "C:\folder2"    
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition

gci $scriptPath -recurse -include $fileFilter | Where {$_.FullName -notlike "$folderExclude*"} 

我的测试文件结构如图所示

C:.
│   Myscript.ps1
│
├───folder1
│   │   file1.dat
│   │   file1.hgr
│   │   file1.txt
│   │
│   └───folder3
│           file3.dat
│           file3.hgr
│           file3.txt
│
└───folder2
        file3.dat
        file3.hgr
        file3.txt

我想要什么

现在我想替换第二行

$folderExclude = "C:\folder2"

带有一个数组。后来有几十条路在里面。

$folderExclude = @(
        "C:\folder2", 
        "C:\folder1\folder3"    
        )

显然这不起作用,因为-notlike 需要一个字符串而不是字符串数组。

我不知道如何实现这一点。我想我需要一个 for-each 循环?

【问题讨论】:

    标签: powershell foreach


    【解决方案1】:

    一种方法是从 $folderExclude 构建一个匹配任何排除字符串(使用交替)的正则表达式,然后使用 -notmatch 而不是 -notlike。

    $folderExclude = @(
        "C:\folder2", 
        "C:\folder1\folder3"    
        )
    
    [regex]$Exclude_regex = ‘(?i)^(‘ + (($folderExclude |foreach {[regex]::escape($_)}) –join “|”) + ‘)’
    
    $fileInclude = @("*.txt", "*.hgr", "*.dat")           
    $scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
    
    gci $scriptPath -recurse -include $fileFilter | Where {$_.FullName -notmatch $Exclude_regex}
    

    编辑:这可能不像嵌套的 where-object 那样“时髦”,但它会更快。

    【讨论】:

      【解决方案2】:

      你也可以走这条路:

      $exclude = @('c:\folder2*', 'c:\folder1\folder3'} 
      gci | Where {$fn = $_.Fullname; ($exclude | Where {$fn -like $_}).count -eq 0}
      

      如果您使用的是 V4,则可以使用方便的新通用参数 -PipelineVariable:

      gci -pv fse | Where {($exclude | Where {$fse.FullName -like $_}).count -eq 0}
      

      请注意,这种方法有一个缺陷,如果 folder1 包含一个名为 folder3foobar 的文件,该文件将被排除在外。要解决此问题,您需要将排除项修改为 c:\folder1\folder3*,然后在与 fse.FullName 进行比较时,如果 fse 是目录而不是文件,则需要附加反斜杠。

      这是另一种基于-match 的方法,允许左侧的数组:

       gci | Where {!($exclude -match [regex]::escape($_.Fullname))}
      

      在这种情况下,如果其中一个目录确实与 $exclude 术语数组匹配,则将输出并强制为 true,但随后会被 ! 反转。

      【讨论】:

      • 我不明白你的第一个例子是如何工作的。能给我解释一下吗?
      • 命令 Where(或 Where-Object)仅期望返回一个可以解释为真或假的值。在该谓词脚本块内(在 {} 内),只要最终结果正确返回 true 或 false(或可以强制为 true/false 的东西),您就可以执行您想要的任何代码。所以在 Where 脚本块中,我存储了目录或文件的全名。然后我创建一个新管道,将 $exclude 数组的每个元素发送到该管道。它包含在 () 中以收集输出。然后我们用count prop查询看看有没有输出
      • 你的第一个例子对我有用。但是我无法使用您或 mjolinor 的正则表达式解决方案。查看gist.github上的代码
      • 当您尝试正则表达式时发生了什么?我对此进行了测试,对我来说效果很好。
      猜你喜欢
      • 1970-01-01
      • 2020-06-17
      • 2013-02-24
      • 1970-01-01
      • 1970-01-01
      • 2020-09-08
      • 1970-01-01
      • 1970-01-01
      • 2019-08-26
      相关资源
      最近更新 更多