簡體   English   中英

如何使用 PowerShell 解析文件夾和文件?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM