使用PowerShell循环浏览目录中的文件


243

如何更改以下代码以查看目录中的所有.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

Answers:


362

试试看:

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)-但我通过首先创建完整文件的备份,然后对原始文件进行更改来进行管理。
user2725402

6
对于v1,您可以使用以下命令提取基本名称:[io.path] :: GetFileNameWithoutExtension($ name)
Shay Levy

如果我替换BaseNameFullName我想要的东西。
M–

77

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

$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

@ user2725402我添加了一个名为<输入文件名> out的输入从属输出文件
PVitt 2013年

不知道我在做什么错,但这不起作用-我现在没有输出文件(也没有错误): $files = Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files\" $files | Where-Object { $outFile = $_.Name + "out" Get-Content $_.FullName | Where-Object { $_ -match 'step4' -or $_ -match 'step9' } | Set-Content $outFile }
user2725402 2013年

2
您也可以这样做foreach ($f in Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files\") { ... }
Soapy 2015年

1
或使用ForEach ($f in $files){...}
Mark Schultheiss '18

31

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

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

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

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

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


让我感到困扰的是忽略了隐藏文件和/或系统文件。要同时看到它们,您必须使用-ForceGet-ChildItem参数。请参阅其文档,网址docs.microsoft.com/en-us/powershell/module/…
til_b

-6

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

每次都会覆盖新文件:

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

如果您覆盖了LogIn文件并希望保留数据,则此操作将附加日志输出:

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

注意:为了能够全局使用GNUWin32 utils,必须将bin文件夹添加到系统路径中。


18
这个问题被标记为PowerShell,而不是Unix
SteveC 2016年

2
是。明显。我的想法很简单:您可以在Windows中使用GNUWin32 utils,因此可以在Powershell中轻松使用* nix工具。作品。没有人说过,答案必须完全是Powershell所固有的。即使这样做,您仍然可以直接从Powershell调用Win32 Utils。使用任何可用的和兼容的AFAIK实际上并不是一件坏事。
user1628658 '17

2
我本来可以编辑我先前的评论,但是我超过了5分钟的限制:SteveC:您是说并入可以在Windows下正常工作的GNU工具在某种程度上违背了Powershell吗?那是一回事。我知道,仅在Powershell中进行这项工作短期内可能会更有成效。从长远来看,可能性实际上具有更多的优点。您添加了更多选项,并且完全可以在Windows和Powershell中运行,而没有Cygwin等任何Linux模拟器。因此,虽然我了解您的保留,但我不同意。
user1628658 '17

5
问题是关于在PowerShell中查找,而不是可以使用的其他多种语言。
SteveC

1
答案就是要解决这个问题。这个问题很明确,因为它需要PowerShell中的答案。您的答案是安装并使用它。您可能已经建议安装Ruby等。
。– SteveC,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.