在 powershell 中列出并 cat 所有包含字符串 X 的文件的方法

在 powershell 中列出并 cat 所有包含字符串 X 的文件的方法

目前,当我在 powershell 中查看一堆文件中的字符串时,我使用以下命令:

PS: C:\> ls -r | Select-String "dummy" | ls -r

这样就列出了所有包含该字符串的文件。如果我执行以下任一操作

PS: C:\> ls -r | Select-String "dummy" | ls -r | cat
PS: C:\> ls -r | Select-String "dummy" | cat

它将再次搜索并 cat 所有包含该字符串的文件,但所有内容都会出现在一个块中,例如

file 1 line 1
file 1 line 2
file 2 line 1
file 3 line 1
file 4 line 1

但是没有办法知道哪一行在哪个文件中。有没有办法让它列出类似以下内容的内容:

File 1.txt:
file1 line1
file2 line2

File 2.txt:
file2 line1

等等。最好只写一行,但不是必须的

答案1

有人可能会说这不是一行代码,但它在任何情况下都应该有效(“应该”的意思是我没有测试过,但脚本应该是正确的):

Get-ChildItem -Recurse | Where-Object {(Select-String -InputObject $_ -Pattern 'dummy' -Quiet) -eq $true} | ForEach-Object {Write-Output $_; Get-Content $_}

扩展并附有评论:

# Get a listing of all files within this folder and its subfolders.
Get-ChildItem -Recurse |

# Filter files according to a script.
Where-Object {
    # Pick only the files that contain the string 'dummy'.
    # Note: The -Quiet parameter tells Select-String to only return a Boolean. This is preferred if you just need to use Select-String as part of a filter, and don't need the output.
    (Select-String -InputObject $_ -Pattern 'dummy' -Quiet) -eq $true
} |

# Run commands against each object found.
ForEach-Object {
    # Output the file properties.
    Write-Output $_;

    # Output the file's contents.
    Get-Content $_
}

如果你真的想看得更短,这里有一个“高尔夫”版本。这绝对更接近“单行”的水平。

ls -R|?{$_|Select-String 'dummy'}|%{$_;gc $_}

除了明显使用别名、空格折叠和参数名称截断之外,您可能还需要注意“完整”版本和“高尔夫”版本之间的以下显著差异:

  • Select-String被换成使用管道输入而不是-InputObject
  • -Pattern省略了参数名称,Select-String因为该参数名称的使用是可选的。
  • -Quiet选项已从 中删除Select-String。过滤器仍将工作,但需要更长时间,因为Select-String它将处理每个完整文件,而不是在第一个匹配的行后停止。
  • -eq $true已从过滤规则中省略。当过滤脚本已经返回布尔值时,如果您只是希望它在布尔值为真时起作用,则无需添加比较运算符和对象。
    • (还请注意,这将适用于某些非布尔值,就像在此脚本中一样。这里,匹配将导致填充的数组对象,该对象被视为真,而非匹配将返回一个空数组,该数组被视为假。)
  • Write-Output被省略。如果未使用命令给出对象,PowerShell 将尝试将此作为默认操作执行。

如果您不需要所有文件的属性,而只想要文件内容前一行的完整路径,则可以使用此方法:

ls -R|?{$_|Select-String 'dummy'}|%{$_.FullName;gc $_}

相关内容