以下工作代码列出了放置脚本的所有子文件夹中的所有文件 它仅包含某些文件类型,并排除某个文件夹中的所有文件。到目前为止一切顺利
$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循环?
答案 0 :(得分: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但后来被!
反转。
答案 1 :(得分: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”,但它会快得多。