我对Powershell相当陌生,遇到了一点麻烦。我已经创建了一个包含多个目录中所有文件及其扩展名的列表,目的是进行字符串模式匹配以检索我感兴趣的文件(具有扩展名和匹配的字符串模式)。
$directory = 'c:test', 'd:testtest'
$files = Get-ChildItem -file $directory -recurse | Select-Object Fullname, extension
$patterns = Get-Content -Path 'C:Patterns.txt'
$files | Select-String -pattern $patterns | Select-Object Pattern, Line
当我运行Select-String来匹配时,我的输出有@{Fullname = C:testtest0001.txt;扩展名= .txt}等
是否有一种方法可以让输出看起来更像下面并将其导出为CSV文件?
Fullname | 扩展名 | 00001 | C: test test00001.txt | . txt |
---|---|---|
00002 | D: 测试 00002.多克斯 | 。docx |
尝试下面的操作,将常用的-PipelineVariable
参数与计算出的属性结合使用:
Get-ChildItem -PipelineVariable file -File $directory -Recurse |
Select-String -Pattern (Get-Content -Path 'C:Patterns.txt') |
Select-Object Pattern,
@{ Name='Fullname'; Expression = { $file.FullName } },
@{ Name='Extension'; Expression = { $file.Extension } }
根据需要将上述管道输送到Export-Csv
。
-PipelineVariable file
将Get-ChildItem
发出的每个file-info对象存储在变量$file
中,允许它在稍后的管道段的脚本块中被引用。定义
Select-Object
调用中计算属性值的表达式引用了存储在管道变量$file
中的file-info对象,以便创建输出对象,该输出对象将Select-String
输出对象中的Pattern
属性与输入文件中的属性值结合起来。
至于你试过的:
您的主要问题是您试图将自定义对象(
[pscustomobject]
实例)管道到Select-String
,这导致后者通过自定义对象的字符串化表示进行搜索(产生类似'@{Fullname = ...; extension = ...}'
的字符串,如您的问题[1]所示)-而不是将它们视为表示文件其内容您想要搜索。要实现这一点,必须使用file-info对象(
[System.IO.FileInfo]
实例)作为输入,直接由Get-ChildItem
发出。为完整起见:
- 如果你的非文件-信息输入对象有一个反映感兴趣的文件路径的属性,比如在你的情况下,你可以使其工作,即通过延迟绑定脚本块传递给
Select-String
的-LiteralPath
参数:$files | Select-String -LiteralPath { $_.Fullname } ...
类似地,如果你的自定义对象有一个
LiteralPath
(或PSPath
,或在PowerShell (Core) 7+中,LP
)属性包含感兴趣的文件路径,管道Select-String
应该按原来的方式工作,因为该属性的值应该自动绑定到-LiteralPath
参数(这种机制,实际上,是System.IO.FileInfo
实例绑定到-LiteralPath
的方式-见这个答案的解释);然而,在PowerShell 7.2.2中,这似乎是在Select-String
中被打破的,具体来说:参见GitHub issue #17188。- 如果你的非文件-信息输入对象有一个反映感兴趣的文件路径的属性,比如在你的情况下,你可以使其工作,即通过延迟绑定脚本块传递给
第二个问题是,你的
Select-Object
调用只操作由Select-String
发出的输出对象,这是[Microsoft.PowerShell.Commands.MatchInfo]
实例,没有.Fullname
和.Extension
属性。
[1]注意,这个字符串表示是简单的.ToString()
字符串化的结果;它是而不是,您将在控制台中看到丰富的表示形式,由PowerShell的for-display输出格式化系统提供。
这感觉有点不对劲,但它是有效的。我感觉有更好的方法将Line属性转换为哈希表对象,但我尝试了Invoke-Expression和ConvertFrom-StringData,但没有成功。
$directory = 'c:test', 'd:testtest'
$files = Get-ChildItem -File $directory | Select-Object FullName, Extension
$exportObj = $files | Select-String -Pattern $patterns | Select-Object Pattern, Line | %{
$line = $_.Line -replace "[@,{,}]","" -split ";"
[PSCustomObject]@{
Pattern=$_.Pattern
FullName=($line[0] -split "=")[1]
Extension=($line[1] -split "=")[1]
}
}
$exportObj | Export-Csv -Path C:temptest.csv -NoTypeInformation