[英]How to parse through folders and files using PowerShell?
我正在嘗試構建一個在特定文件夾和其中的日志文件中移動的腳本,並過濾錯誤代碼。 之后,它將它們傳遞到一個新文件中。
我不太確定如何使用 for 循環來做到這一點,所以我將在下面留下我的代碼。
如果有人能告訴我我做錯了什么,那將不勝感激。
$file_name = Read-Host -Prompt 'Name of the new file: '
$path = 'C:\Users\user\Power\log_script\logs'
Add-Type -AssemblyName System.IO.Compression.FileSystem
function Unzip
{
param([string]$zipfile, [string]$outpath)
[System.IO.Compression.ZipFile]::ExtractToDirectory($zipfile, $outpath)
}
if ([System.IO.File]::Exists($path)) {
Remove-Item $path
Unzip 'C:\Users\user\Power\log_script\logs.zip' 'C:\Users\user\Power\log_script'
} else {
Unzip 'C:\Users\user\Power\log_script\logs.zip' 'C:\Users\user\Power\log_script'
}
$folder = Get-ChildItem -Path 'C:\Users\user\Power\log_script\logs\LogFiles'
$files = foreach($logfolder in $folder) {
$content = foreach($line in $files) {
if ($line -match '([ ][4-5][0-5][0-9][ ])') {
echo $line
}
}
}
$content | Out-File $file_name -Force -Encoding ascii
在 LogFiles 文件夾中還有另外三個文件夾,每個文件夾都包含日志文件。 謝謝
擴展上面關於遞歸文件夾結構的評論,然后實際檢索文件的內容,您可以嘗試以下內容:
$allFiles = Get-ChildItem -Path 'C:\Users\user\Power\log_script\logs\LogFiles' -Recurse
# iterate the files
$allFiles | ForEach-Object {
# iterate the content of each file, line by line
Get-Content $_ | ForEach-Object {
if ($_ -match '([ ][4-5][0-5][0-9][ ])') {
echo $_
}
}
}
看起來您的內部循環是一個尚不存在的集合( $files
)。 您將$files
分配給ForEach(...)
循環的 output 然后嘗試在其中嵌套另一個$files
循環。 當然此時$files
不可循環使用。
無論如何,問題是您從不閱讀日志文件的內容。 即使您設法遍歷Get-ChildItem
的 output ,您也需要查看每一行來執行匹配。
顯然我無法完全測試這一點,但我看到了一些問題並重寫如下:
$file_name = Read-Host -Prompt 'Name of the new file'
$path = 'C:\Users\user\Power\log_script\logs'
$Pattern = '([ ][4-5][0-5][0-9][ ])'
if ( [System.IO.File]::Exists( $path ) ) { Remove-Item $path }
Expand-Archive 'C:\Users\user\Power\log_script\logs.zip' 'C:\Users\user\Power\log_script'
Select-String -Path 'C:\Users\user\Power\log_script\logs\LogFiles\*' -Pattern $Pattern |
Select-Object -ExpandProperty line |
Out-File $file_name -Force -Encoding ascii
注意: Select-String
不能自行遞歸。
我不確定您是否需要編寫自己的UnZip
function。 PowerShell 具有Expand-Archive
cmdlet,它至少可以匹配迄今為止的功能:
Expand-Archive -Path <SourceZipPath> -DestinationPath <DestinationFolder>
注意: -Force
參數允許它覆蓋已經存在的目標文件。 這可以替代測試文件是否存在,如果存在則刪除。
如果您要測試該文件的代碼部分可以簡化為:
if ( [System.IO.File]::Exists( $path ) ) { Remove-Item $path }
Unzip 'C:\Users\user\Power\log_script\logs.zip' 'C:\Users\user\Power\log_script'
這是因為您無論如何都要運行UnZip
命令...
注意:您也可以為此使用Test-Path
。
還有很多獲取匹配行的方法,這里有幾個額外的示例:
Get-ChildItem -Path 'C:\Users\user\Power\log_script\logs\LogFiles' |
ForEach-Object{
( Get-Content $_.FullName ) -match $Pattern
# Using match in this way will echo the lines that matched from each run of
# Get-Content. If nothing matched nothing will output on that iteration.
} |
Out-File $file_name -Force -Encoding ascii
這種方法將在運行匹配之前將整個文件讀入一個數組。 對於大文件,它可能會造成 memory 問題,但它啟用了 -match 的巧妙使用。
或者:
Get-ChildItem -Path 'C:\Users\user\Power\log_script\logs\LogFiles' |
Get-Content |
ForEach-Object{ If( $_ -match $Pattern ) { $_ } } |
Out-File $file_name -Force -Encoding ascii
注意:您不需要別名 echo 或其真正的 cmdlet Write-Output
更新:在摸索了一下並嘗試了不同的東西之后,我終於讓它工作了。
我將包含下面的代碼僅用於演示目的。
感謝大家
$start = Get-Date
"`n$start`n"
$file_name = Read-Host -Prompt 'Name of the new file: '
Out-File $file_name -Force -Encoding ascii
Expand-Archive -Path 'C:\Users\User\Power\log_script\logs.zip' -Force
$i = 1
$folders = Get-ChildItem -Path 'C:\Users\User\Power\log_script\logs\logs\LogFiles' -Name -Recurse -Include *.log
foreach($item in $folders) {
$files = 'C:\Users\User\Power\log_script\logs\logs\LogFiles\' + $item
foreach($file in $files){
$content = Get-Content $file
Write-Progress -Activity "Filtering..." -Status "File $i of $($folders.Count)" -PercentComplete (($i / $folders.Count) * 100)
$i++
$output = foreach($line in $content) {
if ($line -match '([ ][4-5][0-5][0-9][ ])') {
Add-Content -Path $file_name -Value $line
}
}
}
}
$end = Get-Date
$time = [int]($end - $start).TotalSeconds
Write-Output ("Runtime: " + $time + " Seconds" -join ' ')
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.