脚本列出所有不包含所需内容的文件
Script lists all files that don't contain needed content
我试图在一个目录中查找所有在过去 4 小时内修改过且包含字符串的文件。我无法让输出显示不包含所需内容的文件。我如何更改它以便它只列出找到的与字符串匹配的文件名和内容,而不是没有该字符串的文件?这是 运行 作为 windows shell 命令。该目录有数百个文件的不断增长的列表,当前输出如下所示:
File1.txt
File2.txt
File3.txt
... long long list, with none containing the needed string
(powershell "Set-Location -Path "E:\SDKLogs\Logs"; Get-Item *.* | Foreach { $lastupdatetime=$_.LastWriteTime; $nowtime = get-date; if (($nowtime - $lastupdatetime).totalhours -le 4) {Select-String -Path $_.Name -Pattern "'Found = 60.'"| Write-Host "$_.Name Found = 60"; }}")
我尝试更改 Write-Host 的位置,但它仍在打印所有文件。
更新:
我目前正在处理此修复程序。希望这是人们在评论中提到的。
$updateTimeRange=(get-date).addhours(-4)
$fileNames = Get-ChildItem -Path "K:\NotFound" -Recurse -Include *.*
foreach ($file in $filenames)
{
#$content = Get-Content $_.FullName
Write-host "$($file.LastWriteTime)"
if($file.LastWriteTime -ge $($updateTimeRange))
{
#Write-Host $file.FullName
if(Select-String -Path $file.FullName -Pattern 'Thread = 60')
{
Write-Host $file.FullName
}
}
}
如果我没理解错的话,你只是想显示文件名和匹配的内容?如果是这样,以下内容将对您有用:
$date = (Get-Date).AddHours(-4)
Get-ChildItem -Path 'E:\SDKLogs\Logs' | Where-Object -FilterScript { $date -lt $_.LastWriteTime } |
Select-String -Pattern 'Found = 60.' |
ForEach-Object -Process {
'{0} {1}' -f $_.FileName, $_.Matches.Value
}
Get-Date
在您调用之前不需要在变量中,但是,它可能会变得 计算量大 运行再次调用它然后再次。相反,只需将它放在表达式之前的变量中,然后调用 $date
.
的已创建值
通常,为了获得最佳实践,您总是希望在命令中尽可能向左过滤。在这种情况下,我们将您的 if 语句换成 Where-Object
以在对象沿着管道传递时进行过滤。对我们来说幸运的是,Select-String
returns 找到了匹配的文件名,以及匹配的内容,所以我们只是在 Foreach-Object
循环中引用它;也可以使用计算的 属性 代替。
至于您的引用问题,您可能需要在 PowerShell.exe 调用中双引号或将引号转义为 运行 正确。
编辑:将双引号替换为单引号,这样您就可以将整个表达式包裹在 PowerShell.exe -Command "expression here"
中而无需转义;如果您要查找的模式不包含单引号,则此方法有效。
我试图在一个目录中查找所有在过去 4 小时内修改过且包含字符串的文件。我无法让输出显示不包含所需内容的文件。我如何更改它以便它只列出找到的与字符串匹配的文件名和内容,而不是没有该字符串的文件?这是 运行 作为 windows shell 命令。该目录有数百个文件的不断增长的列表,当前输出如下所示:
File1.txt
File2.txt
File3.txt
... long long list, with none containing the needed string
(powershell "Set-Location -Path "E:\SDKLogs\Logs"; Get-Item *.* | Foreach { $lastupdatetime=$_.LastWriteTime; $nowtime = get-date; if (($nowtime - $lastupdatetime).totalhours -le 4) {Select-String -Path $_.Name -Pattern "'Found = 60.'"| Write-Host "$_.Name Found = 60"; }}")
我尝试更改 Write-Host 的位置,但它仍在打印所有文件。
更新: 我目前正在处理此修复程序。希望这是人们在评论中提到的。
$updateTimeRange=(get-date).addhours(-4)
$fileNames = Get-ChildItem -Path "K:\NotFound" -Recurse -Include *.*
foreach ($file in $filenames)
{
#$content = Get-Content $_.FullName
Write-host "$($file.LastWriteTime)"
if($file.LastWriteTime -ge $($updateTimeRange))
{
#Write-Host $file.FullName
if(Select-String -Path $file.FullName -Pattern 'Thread = 60')
{
Write-Host $file.FullName
}
}
}
如果我没理解错的话,你只是想显示文件名和匹配的内容?如果是这样,以下内容将对您有用:
$date = (Get-Date).AddHours(-4)
Get-ChildItem -Path 'E:\SDKLogs\Logs' | Where-Object -FilterScript { $date -lt $_.LastWriteTime } |
Select-String -Pattern 'Found = 60.' |
ForEach-Object -Process {
'{0} {1}' -f $_.FileName, $_.Matches.Value
}
Get-Date
在您调用之前不需要在变量中,但是,它可能会变得 计算量大 运行再次调用它然后再次。相反,只需将它放在表达式之前的变量中,然后调用 $date
.
通常,为了获得最佳实践,您总是希望在命令中尽可能向左过滤。在这种情况下,我们将您的 if 语句换成 Where-Object
以在对象沿着管道传递时进行过滤。对我们来说幸运的是,Select-String
returns 找到了匹配的文件名,以及匹配的内容,所以我们只是在 Foreach-Object
循环中引用它;也可以使用计算的 属性 代替。
至于您的引用问题,您可能需要在 PowerShell.exe 调用中双引号或将引号转义为 运行 正确。
编辑:将双引号替换为单引号,这样您就可以将整个表达式包裹在 PowerShell.exe -Command "expression here"
中而无需转义;如果您要查找的模式不包含单引号,则此方法有效。