使用正则表达式在get-childitem中进行递归筛选时遇到-notmatch问题。

3

使用以下代码查找设置了特定扩展名的文件。

Recursive -notmatch在get-childitem中与正则表达式一起使用。

$include = @('*.keystore', '*.cer', '*crt', '*pfx', '*jks', '*.ks')
$exclude = [RegEx]'^C:\\Windows|^C:\\Program Files|^C:\\Documents and Settings|^C:\\Users|\bBackup\b|\bbackup\b|\brelease\b|\breleases\b|\bReleases\b|\bRelease\b'
$trace="trace.txt"
Get-ChildItem "D:\","C:\" -Directory |
  where FullName -notmatch $exclude | ForEach {
  Get-ChildItem -Path $_.FullName -Include $include -Recurse -Force -EA 0| 
  Select-Object -ExpandProperty FullName 
} *>&1 >> $trace

这个方法有效,但只有当根目录包含其中一个模式时才会排除该目录。例如: 排除 D:\Backup,但包括 D:\something\Backup。

有没有一种方法也能排除第二个文件夹呢?


也许通配符表达式更适合这种情况? - Abraham Zinala
1
我认为你的正则表达式没有问题;'D:\something\Backup' -match $exclude 返回 $true,就像预期的那样。 - mklement0
1
此外,如果您显式构造一个 [regex] 实例 - 而不是将 字符串 传递给 -notmatch - 您将创建一个区分大小写的正则表达式实例。相比之下,隐式使用字符串创建一个不区分大小写的实例,与 PowerShell 的基本不区分大小写行为一致;例如,'foo' -match 'FOO' 返回 $true - mklement0
@mklement0 我有D:\something\backup\test.jks。上述内容并不排除它。但是,它排除了D:\backup。通过创建这两个文件夹来测试它。 - Delyan
1
你需要在第一个 Get-ChildItem 调用中也添加 -Recurse,这样像 backup 这样的文件夹就会在目录层次结构的每个级别上被排除。然而,Theo 的解决方案更简单、更高效。 - mklement0
1个回答

4

尝试使用单个调用Get-ChildItem并查找文件。然后在 Where-Object 子句中,使用 DirectoryName 进行过滤以排除输出中不想要的文件夹。

此外,您可以简化正则表达式并对其进行不区分大小写的使用。

尝试:

$include = '*.keystore', '*.cer', '*.crt', '*.pfx', '*.jks', '*.ks'
$exclude = '^C:\\(Windows|Program Files|Documents and Settings|Users)|\bBackup\b|\breleases?\b'
$trace   = 'trace.txt'
Get-ChildItem -Path 'C:\','D:\' -File -Include $include -Recurse -Force -ErrorAction SilentlyContinue | 
  Where-Object { $_.DirectoryName -notmatch $exclude } |
  Select-Object -ExpandProperty FullName |
  Set-Content -Path $trace -PassThru

开关-PassThru使结果也显示在屏幕上。


C:\驱动器包含系统定义的联接点,即使作为管理员运行,您也无法访问。
根据这个答案,您可以更改代码:

$include = '*.keystore', '*.cer', '*.crt', '*.pfx', '*.jks', '*.ks'
$exclude = '^C:\\(Windows|Program Files|Documents and Settings|Users)|\bBackup\b|\breleases?\b'
$trace   = 'trace.txt'
Get-ChildItem -Path 'C:\','D:\' -File -Include $include -Force -Recurse -Attributes !Hidden, !System, !ReparsePoint -ErrorAction SilentlyContinue | 
  Where-Object { $_.DirectoryName -notmatch $exclude } |
  Select-Object -ExpandProperty FullName |
  Set-Content -Path $trace -PassThru

根据您的评论,这里有一个关于如何在远程计算机上执行此操作并将结果文件保存在您的计算机上的示例。
为了演示,我已删除了 -Force 开关,因为您已经说明您不需要捕获隐藏或系统文件。
$remoteComputers = 'PC01', 'PC01'  # your list of remote machine names here
$trace   = 'trace.csv'             # make your output a CSV file, so you can have the computernam in there as well

$result = Invoke-Command -ComputerName $remoteComputers -ScriptBlock {
    $include = '*.keystore', '*.cer', '*.crt', '*.pfx', '*.jks', '*.ks'
    $exclude = '^C:\\(Windows|Program Files|Documents and Settings|Users)|\bBackup\b|\breleases?\b'
    Get-ChildItem -Path 'C:\','D:\' -File -Include $include -Recurse -ErrorAction SilentlyContinue | 
          Where-Object { $_.DirectoryName -notmatch $exclude } |
          # this time, output an object with the current computername and the file fullname combined
          Select-Object @{Name = 'ComputerName'; Expression = {$env:COMPUTERNAME}}, FullName
}

# save the resulting array of objects in a single CSV file on YOUR local computer
$result | Set-Content -Path $trace -PassThru

您可能需要在Invoke-Command命令中追加参数-Credential并提供远程计算机的管理员凭据。


谢谢,它可以工作,但是由于某种原因它不能使用C:\,即使使用-EA0和管理员权限也会出现Get-ChildItem:拒绝访问的错误。 - Delyan
@Delyan,请查看我的编辑,我已经添加了代码,希望能够防止在C:\驱动器上出现访问被拒绝的情况。 - Theo
谢谢。问题出在一个已安装软件和它的其中一个文件夹上。移除了“-force”,现在不再出现错误。可能这不会成为问题。 - Delyan
1
@Delyan 没问题。移除“-Force”将会起作用,但是它会跳过所有隐藏和/或系统文件(我认为你不需要这些,所以应该没问题)。 - Theo
有什么想法为什么这在远程服务器上不起作用?$trace没有被填充。如果我删除过滤器并列出磁盘,例如它就可以工作。 - Delyan
@Delyan 请查看我的编辑。 - Theo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接