【问题标题】:Powershell how to get-content across several subfoldersPowershell如何跨多个子文件夹获取内容
【发布时间】:2022-06-23 13:38:40
【问题描述】:

我正在编写一个脚本,以根据字符串搜索从多个文件中输出一些数据。它输出找到的字符串,后跟以下六个字符。我可以让它在一个确切的位置工作。但是,我想搜索路径中多个子文件夹内的文件。使用下面的脚本,我得到 PermissionDenied 错误...

[regex] $pattern = '(?<=(a piece of text))(?<chunk>.*)'
Get-Content -Path 'C:\Temp\*' |
ForEach-Object {
  if ($_ -match $pattern) {
    $smallchunk = $matches.chunk.substring(0, 6)
  }
}
    
"$smallchunk" | Out-File  'C:\Temp\results.txt'

如果我将-Path 更改为其中一个子文件夹,它可以正常工作,但我需要它进入每个子文件夹并执行获取内容。

例如,看看里面...

C:\Temp\folder1\*
C:\Temp\folder2\*
C:\Temp\folder3\*

等等……

【问题讨论】:

  • 您可能想看看Select-String。该文档提供了一些示例,说明如何在多个文件和子文件夹中进行搜索。
  • 也许Get-ChildItem -Path C:\temp\ -Filter *.txt -File -Recurse | ForEach-Object { $PSItem | Get-Content } ?
  • @JoseFz 我应该在该代码中的哪个位置放置搜索字符串“一段文本”?
  • Get-Content 之后继续使用您的管道。顺便说一句,代码(原样)也采用C:\Temp\results.txt 文件……我将开始使用Get-ChildItem -Path C:\temp\ -Filter *.txt -File -Recurse | ForEach-Object { $PSItem.FullName} 来查看详细信息。

标签: powershell


【解决方案1】:

根据boxdogSelect-String 的建议,唯一的限制是文件夹递归。不幸的是,Select-String 只允许在一个目录中搜索多个文件。

因此,解决此问题的方法是将Get-ChildItem 的输出与-Recurse 切换到Select-String

$pattern = "(?<=(a piece of text))(?<chunk>.*)"
Get-ChildItem -Path "C:\Temp\" -Exclude "results.txt" -File -Recurse | 
    Select-String -Pattern $pattern |
    ForEach-Object -Process {
        $_.Matches[0].Groups['chunk'].Value.Substring(0,6)
    } | Out-File -FilePath "C:\Temp\results.txt"

如果需要将结果保存到$smallchunk,如果需要,您仍然可以在循环内执行此操作。

【讨论】:

  • chunk 是正则表达式捕获组的自选名称 ((?&lt;chunk&gt;.*))
  • 对我来说,-Append 方法有两个缺点:(a) 必须事先确保目标文件为空;(b) 每次编写匹配时打开和关闭文件都是时间-消耗。请注意,即使 Out-File 在单独的最后段 streaming 处理中也会发生;也就是说,每个匹配都是由ForEach-Object 发出的;唯一的区别是文件只打开和关闭一次。
  • @mklement0 在理想世界中Out-File 会检测到更多输入来自管道并保持文件流打开:p
  • @Abraham 正确:不需要 -AppendOut-File 在其自己的最终管道段中:无论接收到什么管道输入,无论写入什么以及涉及多少其他 cmdlet,是保存到输出文件。 Out-File 每次调用时都必须关闭并打开输出文件 - 如果没有,它将使文件保持打开状态。但是,通过管道输入,它会在begin 块中打开(创建)输出文件,松散地说,将所有管道输入写入process 块中,然后在end 块中关闭文件。
  • @Santiago,但这正是它对管道输入的作用;您只需要确保要写入文件的所有内容都由 single 管道提供。
【解决方案2】:

Abraham Zinala's helpful answer 是您问题的最佳解决方案,因为让Select-String 搜索您的文件内容比使用Get-Content 读取和处理每一行更快且更节省内存。


至于你尝试了什么

使用下面的脚本我得到 PermissionDenied 错误...

这些源于 directoriesGet-ChildItem 输出的文件系统项之一,Get-Content 无法读取。

如果您的文件具有您的目录没有的不同文件扩展名,一种选择是将它们传递给(很少与Get-Content 一起使用)-Include 参数;例如:

Get-Content -Path C:\Temp\* -Include *.txt, *.c 

但是,与Select-String 一样,这将您限制为单个 目录的内容,并且它不允许您从根本上将处理限制为文件,如果扩展基于 - 的过滤是不可能的。

对于递归列表,您可以使用Get-ChildItem-Recurse,如亚伯拉罕的回答,并将文件信息对象通过管道传递给Get-Content

Get-ChildItem -Recurse C:\Temp -Include *.txt, *.c | Get-Content

如果您只想将输出限制为文件,无论它们的名称是什么,请使用-File 开关(类似地,-Directory 将输出限制为目录):

Get-ChildItem -File -Recurse C:\Temp | Get-Content

【讨论】:

    猜你喜欢
    • 2018-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多