是否可以暂时将.ZIP文件(7-Zip)的内容扩展到内存中的变量,操作内容并使用PowerShell丢弃它?
我目前正在扩展档案,它提取了一个"log.dat“文件。然后我读取了这个日志文件的内容,做了分析并删除了"log.dat“文件。但我得做500,000次,这可能会对驾驶有害。所以现在,我的解决办法是创建一个R:\ RamDrive并像这样使用它
$zipFiles = Get-ChildItem -Filter '*.zip' -r
foreach($zip in $zipFiles) {
Expand-7Zip -ArchiveFileName $zip.FullName -TargetPath 'R:\'
Select-String -Path 'R:\log.dat' -Pattern "dataToSearchFor" | ForEach-Object {
# do analysis
}
Remove-Item 'R:\log.dat'
}我需要的是
$zipFiles = Get-ChildItem -Filter '*.zip' -r
foreach($zip in $zipFiles) {
$extractedFiles = Expand-7Zip -ArchiveFileName $zip.FullName
$logFile = $extractedFiles[0] # log.dat file is unique in file
Select-String $logFile -Pattern "dataToSearchFor" | ForEach-Object {
# do analysis
}
}顺便说一句:我必须为PowerShell使用7-zip库,因为档案中使用了压缩方法。
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
Set-PSRepository -Name 'PSGallery' -SourceLocation "https://www.powershellgallery.com/api/v2" -InstallationPolicy Trusted
Install-Module -Name 7Zip4PowerShell -Force发布于 2022-11-06 02:49:36
他们说“第三次是一种魅力。”
这是我第三次尝试解决这个问题。第二次尝试的信息仍然有效,但是只对某些压缩文件有效,所以您可以在这个答案中找到更深入的信息。
First,从https://www.7-zip.org/安装7-zip的最新版本.
在我的例子中,安装了7z2201-x64.exe。
第二个,下载SevenZipSharp的Nuget包,然后使用7-Zip打开包,导航到sevenzipsharp.net45.1.0.19.nupkg\lib\net45\并将SevenZipSharp.dll保存到与PowerShell脚本相同的位置。
以下任何一项似乎都适用于下载:https://www.nuget.org/api/v2/package/SevenZipSharp.Net45/1.0.19
或
https://globalcdn.nuget.org/packages/sevenzipsharp.net45.1.0.19.nupkg
第三版,注意安装7-Zip的7z.dll文件的位置.在我的例子中,是C:\Program Files\7-Zip\7z.dll。
Forth,将以下行添加到PowerShell脚本的顶部,确保给SetLibraryPath的路径设置为7-Zip在上面的第三步中找到的7z.dll的路径。
using namespace System.IO
Add-Type -Path "$PSScriptRoot\SevenZipSharp.dll"
[SevenZip.SevenZipExtractor]::SetLibraryPath('C:\Program Files\7-Zip\7z.dll')第五,添加您想要运行的代码。
此示例读取在存档文件SevenZipTest.zip中找到的所有文件路径名称,这些文件路径与PowerShell脚本的路径相同:
function ReadFilenamesIn7Zip {
param (
[Parameter(Mandatory = $true, Position = 0)]
[string]$Path
)
[SevenZip.SevenZipExtractor]$ZipArchive = [SevenZip.SevenZipExtractor]::new($Path)
foreach($ArchiveFileInfo in $ZipArchive.ArchiveFileData) {
$ArchiveFileInfo.FileName
}
$ZipArchive.Dispose()
}
ReadFilenamesIn7Zip "$PSScriptRoot\SevenZipTest.zip"此示例从名为Test.TXT的第一个内部文件中读取所有文件行,该文件位于与PowerShell脚本相同的路径中的归档文件SevenZipTest.zip中:
function ReadFileIn7Zip {
param (
[Parameter(Mandatory = $true, Position = 0)]
[string]$Path,
[Parameter(Mandatory = $true, Position = 1)]
[string]$FileToUnzip,
[Parameter(Mandatory = $false, Position = 2)]
[int]$FileIndex = -1
)
[SevenZip.SevenZipExtractor]$ZipArchive = [SevenZip.SevenZipExtractor]::new($Path)
$ThisFileIndex = 0
foreach($ArchiveFileInfo in $ZipArchive.ArchiveFileData) {
$FileNameNoPath = Split-Path $ArchiveFileInfo.FileName -leaf
if($FileNameNoPath -eq $FileToUnzip) {
if($FileIndex -lt 0 -or $FileIndex -eq $ThisFileIndex) {
$MemoryStream = [System.IO.MemoryStream]::new()
$ZipArchive.ExtractFile($ArchiveFileInfo.Index, $MemoryStream)
[StreamReader]$ZipReader = [StreamReader]::new($MemoryStream)
$MemoryStream.Position = 0
while ($null -ne ($line = $ZipReader.ReadLine())) {
$line
}
$ZipReader.Dispose()
# $MemoryStream.Dispose() # Not needed: https://learn.microsoft.com/en-us/dotnet/api/system.io.memorystream?view=net-6.0#remarks
}
$ThisFileIndex++
}
}
$ZipArchive.Dispose()
}
ReadFileIn7Zip "$PSScriptRoot\SevenZipTest.zip" "Test.TXT" 0ReadFilenamesIn7Zip和ReadFileIn7Zip的功能本质上与下面的ReadFilenamesInZip和ReadFileInZip示例相同。例如,如果您查看下面ReadFileInZip函数的功能,当不使用-FileIndex参数调用它时,它将返回与-FileToUnzip参数匹配的所有文件的所有文本,这对于ReadFileIn7Zip也是如此。
注:{来自第二次尝试的信息低于此点。}
下面的* Deflate**,信息只对压缩有 ** BZip2**,和** LZMA压缩的压缩文件有效
本例以zip文件01_SQLite.zip为例,搜索任何名为App.config的文件。这非常类似于注释中提供的链接PowerShell jdweng的读取版本和,但是有几处修改,比如将文件存储在StringBuilder中。
更新:代码在VSCode中工作,但发现它不在PowerShell 5.1终端中工作。两者应该是相同的,但由于某些原因,它们不是-而且VSCode被设置为在每次运行脚本之前重新加载PowerShell,所以不应该有任何预加载的程序集。
解决方案:谢谢圣地亚哥,在代码中添加了Add-Type -Assembly System.IO.Compression, System.IO.Compression.FileSystem。通过关闭PowerShell终端、重新打开它并运行脚本来验证它的有效性:
using namespace System.IO
using namespace System.IO.Compression
using namespace System.IO.MemoryStream
using namespace System.Text
Add-Type -Assembly System.IO.Compression, System.IO.Compression.FileSystem
$ZipFilePath = "$PSScriptRoot\01_SQLite.zip"
[ZipArchive]$ZipArchive = [ZipFile]::Open($ZipFilePath, [ZipArchiveMode]::Read)
[StringBuilder]$SB = [StringBuilder]::new()
foreach($ZipEntry in $ZipArchive.Entries) {
if($ZipEntry.Name -eq "App.config") {
[StreamReader]$ZipReader = [StreamReader]::new($ZipEntry.Open())
while ($null -ne ($line = $ZipReader.ReadLine())) {
$null = $SB.AppendLine($line)
}
# Do something with the file stored in StringBuilder $SB
Write-Host "Found file $($ZipEntry.FullName)"
Write-Host $SB.ToString()
Write-Host
$null = $SB.Clear()
$ZipReader.Dispose()
}
}
$ZipArchive.Dispose()更多用途和更有用的代码:
此函数返回Zip文件中找到的文件路径和名称:
using namespace System.IO
using namespace System.IO.Compression
Add-Type -Assembly System.IO.Compression, System.IO.Compression.FileSystem
function ReadFilenamesInZip {
param (
[Parameter(Mandatory = $true, Position = 0)]
[string]$Path
)
[ZipArchive]$ZipArchive = [ZipFile]::Open($Path, [ZipArchiveMode]::Read)
foreach($ZipEntry in $ZipArchive.Entries) {
$ZipEntry.FullName
}
$ZipArchive.Dispose()
}例如,从01_SQLite.zip文件中读取文件路径名:
$ZipFilePath = "$PSScriptRoot\01_SQLite.zip"
$FileNames = ReadFilenamesInZip -Path $ZipFilePath
$FileNames因此产生了这一产出:
screenshot.png
sqlite_test.sln
sqlite_test/App.config
sqlite_test/App.xaml
sqlite_test/App.xaml.cs
sqlite_test/MainWindow.xaml
sqlite_test/MainWindow.xaml.cs
sqlite_test/packages.config
sqlite_test/Properties/AssemblyInfo.cs
sqlite_test/Properties/Resources.Designer.cs
sqlite_test/Properties/Resources.resx
sqlite_test/Properties/Settings.Designer.cs
sqlite_test/Properties/Settings.settings
sqlite_test/sqlite_test.csproj示例使用,从我创建的名为TestZip.zip的zip文件中读取文件路径名
$ZipFilePath = "$PSScriptRoot\TestZip.zip"
$FileNames = ReadFilenamesInZip -Path $ZipFilePath
$FileNames因此产生了这一产出:
Folder1/Test.TXT
Folder2/Test.TXT
Test.TXT此函数返回与某个文件名匹配的所有文件的内容:
using namespace System.IO
using namespace System.IO.Compression
Add-Type -Assembly System.IO.Compression, System.IO.Compression.FileSystem
function ReadFileInZip {
param (
[Parameter(Mandatory = $true, Position = 0)]
[string]$Path,
[Parameter(Mandatory = $true, Position = 1)]
[string]$FileToUnzip,
[Parameter(Mandatory = $false, Position = 2)]
[int]$FileIndex = -1
)
[ZipArchive]$ZipArchive = [ZipFile]::Open($Path, [ZipArchiveMode]::Read)
$ThisFileIndex = 0
foreach($ZipEntry in $ZipArchive.Entries) {
if($ZipEntry.Name -eq $FileToUnzip) {
if($FileIndex -lt 0 -or $FileIndex -eq $ThisFileIndex) {
[StreamReader]$ZipReader = [StreamReader]::new($ZipEntry.Open())
while ($null -ne ($line = $ZipReader.ReadLine())) {
$line
}
$ZipReader.Dispose()
}
$ThisFileIndex++
}
}
$ZipArchive.Dispose()
}从TestZip.zip中提取与文件名Test.TXT匹配的所有内部文件的内容的示例
$ZipFilePath = "$PSScriptRoot\TestZip.zip"
$FileLines = ReadFileInZip -Path $ZipFilePath -FileToUnzip 'Test.TXT'
if ($null -ne $FileLines) {
Write-Host 'Found File(s):'
$FileLines
} else {
Write-Host 'File NOT found.'
}因此产生了这一产出:
Found File(s):
### Folder 1 Text File ###
Random info in Folder 1 text file
### Folder 2 Text File ###
Random info in Folder 2 text file
### Root Text File ###
Random info in root text file示例仅读取具有匹配名称的第一个文件的内容-
注意添加的-FileIndex 0
$ZipFilePath = "$PSScriptRoot\TestZip.zip"
$FileLines = ReadFileInZip -Path $ZipFilePath -FileToUnzip 'Test.TXT' -FileIndex 0
if ($null -ne $FileLines) {
Write-Host 'Found File(s):'
$FileLines
} else {
Write-Host 'File NOT found.'
}因此产生了这一产出:
Found File(s):
### Folder 1 Text File ###
Random info in Folder 1 text file将-FileIndex 0更改为-FileIndex 2可以得到以下结果:
Found File(s):
### Root Text File ###
Random info in root text file将FileIndex更改为不指向zip中的文件的值(如-FileIndex 3 ),将得到以下结果:
File NOT found.https://stackoverflow.com/questions/74332064
复制相似问题