首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用.NET类而不是压缩存档在Powershell中压缩多个目录。

使用.NET类而不是压缩存档在Powershell中压缩多个目录。
EN

Stack Overflow用户
提问于 2022-03-09 09:59:05
回答 1查看 201关注 0票数 0

我试图使用.NET类而不是本机compress-archive来压缩多个目录(每个目录都包含子目录和文件),因为compress-archive给了我偶尔的OutOfMemory异常。

一些文章告诉我.NET类,它提供了一种更优化的方法。

我的tools目录$toolsDir = 'C:\Users\Public\LocalTools'有多个需要压缩的目录(请注意,所有内容都是一个目录,而不是文件)--哪个目录与regex模式匹配,如代码中所示。

下面是我的代码:

代码语言:javascript
复制
$cmpname = $env:computername
$now = $(Get-Date -Format yyyyMMddmmhhss)
$pattern = '^(19|[2-9][0-9])\d{2}\-(0?[1-9]|1[012])\-(0[1-9]|[12]\d|3[01])T((?:[01]\d|2[0-3])\;[0-5]\d\;[0-5]\d)\.(\d{3}Z)\-' + [ regex ]::Escape($cmpname)
$toolsDir = 'C:\Users\Public\LocalTools'
$destPathZip = "C:\Users\Public\ToolsOutput.zip"

 
Add-Type -AssemblyName System.IO.Compression
Add-Type -AssemblyName System.IO.Compression.FileSystem
$CompressionLevel = [ System.IO.Compression.CompressionLevel ]::Optimal
$IncludeBaseDirectory = $false
$stream = New-Object System.IO.FileStream($destPathZip , [ System.IO.FileMode ]::OpenOrCreate)
$zip = New-Object System.IO.Compression.ZipArchive($stream , 'update')

 
$res = Get-ChildItem "${toolsDir}" | Where-Object {$_ .Name -match "${pattern}"}

if ($res -ne $null) {
    foreach ($dir in $res) {
       $source = "${toolsDir}\${dir}"
       [ System.IO.Compression.ZipFileExtensions ]::CreateEntryFromFile($destPathZip , $source , (Split-Path $source -Leaf), $CompressionLevel)

    }
}
else {
    Write-Host "Nothing to Archive!"

} 

上面的代码给出了这个错误:

当我研究[ System.IO.Compression.ZipFileExtensions ]::CreateEntryFromFile时,它被用来将files添加到已经创建的zip文件中。这就是我得到错误的原因吗?

我也尝试了[ System.IO.Compression.ZipFile ]::CreateFromDirectory($source , $destPathZip , $CompressionLevel, $IncludeBaseDirectory)而不是[ System.IO.Compression.ZipFileExtensions ]::CreateEntryFromFile($destPathZip , $source , (Split-Path $source -Leaf), $CompressionLevel)

这给了我"The file 'C:\Users\Public\ToolsOutput.zip' already exists错误。

如何更改代码,以便在zip文件中添加多个目录。

EN

回答 1

Stack Overflow用户

发布于 2022-03-09 12:29:07

当前,您的代码有三个问题:

传递给purpose.

  • CreateEntryFromFile
  1. 第一个参数必须是一个添加新条目的ZipArchive对象--在您的示例中,您将希望传递已经为该CreateEntryFromFile()创建的$zip,每个调用只为一个文件创建一个条目--以便重新创建一个完整的目录子结构,以计算每个文件的正确入口路径,例如。subdirectory/subsubdirectory/file.exe
  2. You需要正确地处理ZipArchive和底层文件流实例,以便将数据持久化到磁盘上。为此,您需要一个try/finally语句.

此外,如果没有要存档的文件,则无需创建该文件:)

代码语言:javascript
复制
$cmpname = $env:computername
$pattern = '^(19|[2-9][0-9])\d{2}\-(0?[1-9]|1[012])\-(0[1-9]|[12]\d|3[01])T((?:[01]\d|2[0-3])\;[0-5]\d\;[0-5]\d)\.(\d{3}Z)\-' + [regex]::Escape($cmpname)
$toolsDir = 'C:\Users\Public\LocalTools'
$destPathZip = "C:\Users\Public\ToolsOutput.zip"

Add-Type -AssemblyName System.IO.Compression
Add-Type -AssemblyName System.IO.Compression.FileSystem

$CompressionLevel = [System.IO.Compression.CompressionLevel]::Optimal

$res = Get-ChildItem -LiteralPath $toolsDir | Where-Object { $_.Name -match $pattern }

if ($res) {
  try {
    # Create file + zip archive instances
    $stream = New-Object System.IO.FileStream($destPathZip, [System.IO.FileMode]::OpenOrCreate)
    $zip = New-Object System.IO.Compression.ZipArchive($stream, [System.IO.Compression.ZipArchiveMode]::Update)

    # Discover all files to archive
    foreach ($file in $res |Get-ChildItem -File -Recurse) {
      $source = $dir.FullName

      # calculate correct relative path to the archive entry
      $relativeFilePath = [System.IO.Path]::GetRelativePath($toolsDir, $source)
      $entryName = $relativeFilePath.Replace('\', '/')

      # Make sure the first argument to CreateEntryFromFile is the ZipArchive object
      [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($zip, $source, $entryName, $CompressionLevel)
    }
  }
  finally {
    # Clean up in reverse order
    $zip, $stream | Where-Object { $_ -is [System.IDisposable] } | ForEach-Object Dispose
  }
}
else {
  Write-Host "Nothing to Archive!"
}

调用Dispose() on $zip将导致它刷新对底层文件流的任何未写入的修改,并释放它可能获得的任何其他文件句柄,而在底层文件流上调用Dispose()则会将这些更改刷新到磁盘并关闭文件句柄。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71407463

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档