【问题标题】:Loop through files in a directory using PowerShell使用 PowerShell 遍历目录中的文件
【发布时间】:2013-09-21 17:34:07
【问题描述】:

如何更改以下代码以查看目录中的所有 .log 文件,而不仅仅是一个文件?

我需要遍历所有文件并删除所有不包含“step4”或“step9”的行。目前这将创建一个新文件,但我不确定如何在此处使用for each 循环(新手)。

实际文件的命名如下:2013 09 03 00_01_29.log。我希望输出文件要么覆盖它们,要么具有相同的名称,并附加“out”。

$In = "C:\Users\gerhardl\Documents\My Received Files\Test_In.log"
$Out = "C:\Users\gerhardl\Documents\My Received Files\Test_Out.log"
$Files = "C:\Users\gerhardl\Documents\My Received Files\"

Get-Content $In | Where-Object {$_ -match 'step4' -or $_ -match 'step9'} | `
Set-Content $Out

【问题讨论】:

    标签: powershell


    【解决方案1】:

    试试这个:

    Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files" -Filter *.log | 
    Foreach-Object {
        $content = Get-Content $_.FullName
    
        #filter and save content to the original file
        $content | Where-Object {$_ -match 'step[49]'} | Set-Content $_.FullName
    
        #filter and save content to a new file 
        $content | Where-Object {$_ -match 'step[49]'} | Set-Content ($_.BaseName + '_out.log')
    }
    

    【讨论】:

    • 谢谢。 BaseName 部分不起作用(版本 1) - 但我通过首先创建完整文件的备份然后对原始文件进行更改来管理。
    • 对于 v1,您可以使用以下内容提取基本名称:[io.path]::GetFileNameWithoutExtension($name)
    • 如果我将BaseName 替换为FullName 我得到了我想要的。
    【解决方案2】:

    要获取目录的内容,您可以使用

    $files = Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files\"
    

    然后你也可以循环这个变量:

    for ($i=0; $i -lt $files.Count; $i++) {
        $outfile = $files[$i].FullName + "out" 
        Get-Content $files[$i].FullName | Where-Object { ($_ -match 'step4' -or $_ -match 'step9') } | Set-Content $outfile
    }
    

    更简单的表达方式是foreach 循环(感谢@Soapy 和@MarkSchultheiss):

    foreach ($f in $files){
        $outfile = $f.FullName + "out" 
        Get-Content $f.FullName | Where-Object { ($_ -match 'step4' -or $_ -match 'step9') } | Set-Content $outfile
    }
    

    【讨论】:

    • 这将创建一个名为“out.log”的输出文件。如何为每个输入文件创建单独的输出文件?
    • @user2725402 我添加了一个名为 out 的输入依赖输出文件
    • 好的 2 个新问题...现在由于某种原因与匹配相反,即它创建的文件仅包含不包含“step4”或“step9”的记录。此外,它使用“out”作为扩展名进行重命名,因此文件被命名为“XXX.log.out” - 我尝试使用 BaseName 但无法正确使用。
    • 你也可以foreach ($f in Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files\") { ... }
    • 或使用ForEach ($f in $files){...}
    【解决方案3】:

    如果您需要在目录中递归循环以查找特定类型的文件,请使用以下命令,该命令会过滤所有 doc 文件类型的文件

    $fileNames = Get-ChildItem -Path $scriptPath -Recurse -Include *.doc

    如果您需要对多种类型进行过滤,请使用以下命令。

    $fileNames = Get-ChildItem -Path $scriptPath -Recurse -Include *.doc,*.pdf

    现在$fileNames 变量充当一个数组,您可以从中循环并应用您的业务逻辑。

    【讨论】:

    【解决方案4】:

    其他答案很好,我只想添加...在 PowerShell 中可用的不同方法: 安装 GNUWin32 utils 并使用 grep 查看行/将输出重定向到文件 http://gnuwin32.sourceforge.net/

    这每次都会覆盖新文件:

    grep "step[49]" logIn.log > logOut.log 
    

    这会附加日志输出,以防您覆盖 logIn 文件并希望保留数据:

    grep "step[49]" logIn.log >> logOut.log 
    

    注意:为了能够在全局范围内使用 GNUWin32 实用程序,您必须将 bin 文件夹添加到系统路径中。

    【讨论】:

    • 这个问题被标记为 PowerShell,而不是 Unix
    • 是的。明显地。我的看法相当简单:您可以在 Windows 中使用 GNUWin32 实用程序,因此您可以在 Powershell 中轻松使用 *nix 工具。作品。从来没有人说过,答案必须完全来自 Powershell。即使他们这样做了,您仍然可以直接从 Powershell 调用 Win32 Utils。 AFAIK 使用任何可用和兼容的东西实际上并不是一件坏事。
    • 我会编辑我之前的评论,但我超过了 5 分钟的限制: SteveC:你是说整合在 Windows 下可以正常工作的 GNU 工具在某种程度上违背了 Powershell?那是一回事。我知道纯粹在 Powershell 中解决这个问题可能在短期内更有成效。从长远来看,扩大可能性实际上更有好处。您添加了更多选项,并且完全在 Windows 和 Powershell 中工作,没有任何像 Cygwin 这样的 Linux 模拟器。因此,虽然我理解您的预订,但我不同意。
    • 问题是关于在 PowerShell 中查找,而不是可以使用的众多其他语言。
    • 答案是针对问题的。这个问题很明确,因为它需要 PowerShell 中的答案。您的答案是安装并使用它。你可以建议安装 Ruby 等。
    猜你喜欢
    • 1970-01-01
    • 2010-12-16
    • 2017-05-20
    • 1970-01-01
    • 1970-01-01
    • 2012-02-02
    • 2017-09-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多