递归搜索目录以查找内容与正则表达式匹配的文件,并将匹配文件的路径收集到数组中

Recursively search a directory for files whose content matches a regex and collect the paths of matching files in an array

$locations = Get-ChildItem $readLoc -recurse | ? {!$_.psiscontainer} | select-object name | %{$e = $_.name; get-content $e}

$array = @()

for($i = 0; $i -lt $locations.length; $i++){
    #if($locations.name[$i].length -eq "9"){
        $paths = Resolve-Path $locations.fullname[$i]
        $paths.path
        get-content $locations.name[$i]
        #$array += $paths.path 
    #}
}

我需要遍历文件系统中的每个文件并打开每个文件。我正在检查文件中的字符串是否与正则表达式匹配,然后将该文件的完整路径输出到数组中。

但是,$locations 不接受获取内容。

获取内容:找不到路径

'C:\Users\xxxxxx\Documents\files\powershell\OWASP_ApplicationThreatModeling.docx'
because it does not exist.
At line:1 char:89
+ ... .psiscontainer} | select-object name |%{$e = $_.name; get-content $e}
+                                                           ~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\Users\p61782...atModeling.docx:String) [Get-Content], ItemNotFoundEx
   ception
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand.

正如 TheMadTechnician 所建议的,使用 Select-String 执行正则表达式匹配更有效:

$locations = Get-ChildItem $readLoc -File -Recurse |
               Select-String -List -Pattern '^\d{3}-?\d{2}-?\d{4}$' | 
                 Select-Object -ExpandProperty Path

注:
- 传递给 -Pattern 的正则表达式是 linked to in a comment.
的简化版本 请注意正则表达式如何包含在 '...' 而不是 "..." 中,以防止 PowerShell 无意地 预先 解释字符串。

  • Get-ChildItem $readLoc -File -recurse 递归枚举目标目录子树中的所有文件。开关 -File(连同它的对应物,-Directory)在 PSv3+ 中可用,并且不需要 ? {!$_.psiscontainer} 过滤器。

  • Select-String 可以对通过 Get-ChildItem 传输的文件的 content 进行操作,并默认执行正则表达式匹配:

    • -List 告诉 Select-String 仅 return 来自每个输入文件(如果有)的 第一个 匹配项。
  • Select-String returns 匹配信息对象 .Path 属性 包含完整路径输入文件的路径,因此 Select-Object -ExpandProperty Path 用于仅输出包含至少 1 个匹配项的任何文件的路径。

总体而言,变量 $locations 因此接收到那些文件的完整路径 数组 ,其中至少有 1 行与感兴趣的正则表达式匹配。
请注意,如果输出包含超过 1 个元素,PowerShell 会自动收集 数组 中命令的输出。


至于你尝试了什么:

  • 您的直接问题是您将 .Name - 即一个文件 name - 传递给了 Get-Content 而不是 .FullName.

  • 此外,您的明显意图是在数组 $locations 中收集 文件信息对象 ,而您的管道实际上产生了 所有文件的内容(作为行数组)。

您需要与 FullName 属性 合作。现在您正在使用 Select-Object 命令删除它。

$locations = Get-ChildItem $readLoc -recurse | ? {!$_.psiscontainer}

for($i = 0; $i -lt $locations.length; $i++){
    $locations[$i].fullname
    get-content $locations[$i].fullname
}