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

时间:2017-06-14 18:31:00

标签: powershell powershell-v4.0

$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并不接受get-content。

get-content:找不到路径

'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.

2 个答案:

答案 0 :(得分:1)

正如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以递归方式枚举目标目录子树中的所有文件。在PSv3 +中可以使用切换-File(及其对应的-Directory),并且无需使用? {!$_.psiscontainer}过滤器。

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

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

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

至于你的尝试:

  • 您当前的问题是您将.Name - 即仅仅是文件名称 - 传递给Get-Content而不是.FullName

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

答案 1 :(得分:0)

您需要使用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
}