【问题标题】:Recursive -notmatch in get-childitem with regex使用正则表达式的 get-childitem 中的递归 -notmatch
【发布时间】:2022-01-31 20:02:35
【问题描述】:

使用正则表达式在 get-childitem 中递归 -notmatch

我正在尝试使用以下代码查找一些具有设置扩展名的文件。

$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

有没有办法排除第二个文件夹?

【问题讨论】:

  • 也许通配符表达式更适合这个?
  • 我看不出你的正则表达式有问题; 'D:\something\Backup' -match $exclude 按预期返回 $true
  • 另外,如果你明确地构造一个[regex] 实例——而不是将一个字符串传递给-notmatch——你正在创建一个大小写——敏感 i> 正则表达式实例。相比之下,使用字符串会隐式创建一个不区分大小写的实例,这符合 PowerShell 基本不区分大小写的行为;例如'foo' -match 'FOO' 返回$true
  • @mklement0 我有 D:\something\backup\test.jks。以上不排除。但是,不包括 D:\backup。通过创建这 2 个文件夹来测试它。
  • 您还需要将-Recurse 添加到first Get-ChildItem 调用中,以便在目录层次结构的每个级别上排除诸如backup 之类的文件夹。然而,Theo 的解决方案更简单、更高效。

标签: powershell


【解决方案1】:

尝试一次调用Get-ChildItem 并让它查找文件。然后在 Where-Objectclause 中,过滤 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:\ 驱动器包含系统定义的连接点,即使以管理员身份运行,您也无法访问。
基于this answer,可以将代码改为:

$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

您可能需要将参数 -Credential 附加到 Invoke-Command 并为其提供远程计算机的管理员凭据

【讨论】:

  • 谢谢,它可以工作,但不能使用 C:\,因为某种原因它会提供 Get-ChildItem :即使使用 -EA0 和管理员权限,访问也会被拒绝。
  • @Delyan 请查看我的编辑,我在其中添加了代码以希望防止 C:\ 驱动器上的访问被拒绝
  • 谢谢。问题在于已安装的软件及其文件夹之一。删除 -force ,现在我没有收到错误消息。应该不会有问题。
  • @Delyan 不,没问题。删除 -Force 将起作用,但随后它将跳过所有隐藏和/或系统文件(不要认为你在追求那些,所以应该没问题)
  • 知道为什么这在远程服务器上不起作用吗? $trace 不会被填充。例如,如果我删除过滤器并列出磁盘,它就可以工作。
猜你喜欢
  • 2014-12-10
  • 1970-01-01
  • 2012-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多