5

是)我有的

以下工作代码列出了放置脚本的所有子文件夹中的所有文件。
它仅包括某些文件类型,并排除某个文件夹中的所有文件。到现在为止还挺好

$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 循环?

4

2 回答 2

6

你也可以走这条路:

$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,但随后会被!.

于 2013-11-07T18:26:13.457 回答
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 那样“Posh”,但它会更快。

于 2013-11-07T17:39:46.467 回答