使用 Powershell 或命令行在 Windows 中创建压缩/压缩文件夹

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11021879/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 09:35:41  来源:igfitidea点击:

Creating a zipped/compressed folder in Windows using Powershell or the command line

windowspowershellcommand-linecompression

提问by TechDawg270

I am creating a nightly database schema file and would like to put all the files created each night, one for each database, into a folder and compress that folder. I have a PowerShell script that creates the schema.Only creation script of the db's and then adds all the files to a new folder. The problem lies within the compression portion of this process.

我正在创建一个夜间数据库架构文件,并希望将每晚创建的所有文件(每个数据库一个)放入一个文件夹中并压缩该文件夹。我有一个创建架构的 PowerShell 脚本。只有数据库的创建脚本,然后将所有文件添加到新文件夹中。问题在于这个过程的压缩部分。

Does anybody have any idea if this can be accomplished with the pre-installed Windows utility that handles folder compression?

有没有人知道这是否可以通过处理文件夹压缩的预安装 Windows 实用程序来完成?

It would be best to use that utility if possible rather than something like 7zip (I don't feel like installing 7zip on every customers' server and it may take IT years to do it if I ask them).

如果可能,最好使用该实用程序而不是 7zip 之类的工具(我不想在每个客户的服务器上安装 7zip,如果我问他们,可能需要 IT 数年时间才能完成)。

采纳答案by voithos

Here's a couple of zip-related functions that don't rely on extensions: Compress Files with Windows PowerShell.

下面是几个不依赖于扩展的 zip 相关函数:使用 Windows PowerShell 压缩文件

The main function that you'd likely be interested in is:

您可能感兴趣的主要功能是:

function Add-Zip
{
    param([string]$zipfilename)

    if(-not (test-path($zipfilename)))
    {
        set-content $zipfilename ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
        (dir $zipfilename).IsReadOnly = $false  
    }

    $shellApplication = new-object -com shell.application
    $zipPackage = $shellApplication.NameSpace($zipfilename)

    foreach($file in $input) 
    { 
            $zipPackage.CopyHere($file.FullName)
            Start-sleep -milliseconds 500
    }
}

Usage:

用法:

dir c:\demo\files\*.* -Recurse | Add-Zip c:\demo\myzip.zip

There is one caveat: the shell.applicationobject's NameSpace()function fails to open up the zip file for writing if the path isn't absolute. So, if you passed a relative path to Add-Zip, it'll fail with a null error, so the path to the zip file must be absolute.

有一个警告:如果路径不是绝对路径,shell.application对象的NameSpace()函数将无法打开 zip 文件进行写入。因此,如果您将相对路径传递给Add-Zip,它将失败并返回空错误,因此 zip 文件的路径必须是绝对路径。

Or you could just add a $zipfilename = resolve-path $zipfilenameat the beginning of the function.

或者你可以$zipfilename = resolve-path $zipfilename在函数的开头添加一个。

回答by sonjz

A native way with latest .NET 4.5 framework, but entirely feature-less:

使用最新的 .NET 4.5 框架的本机方式,但完全没有功能:

Creation:

创建:

Add-Type -Assembly "System.IO.Compression.FileSystem" ;
[System.IO.Compression.ZipFile]::CreateFromDirectory("c:\your\directory\to\compress", "yourfile.zip") ;

Extraction:

萃取:

Add-Type -Assembly "System.IO.Compression.FileSystem" ;
[System.IO.Compression.ZipFile]::ExtractToDirectory("yourfile.zip", "c:\your\destination") ;

As mentioned, totally feature-less, so don't expect an overwriteflag.

如前所述,完全没有功能,所以不要指望覆盖标志。

回答by Overly Excessive

As of PowersShell 5 there is a Compress-Archivecmdlet that does the task out of the box.

从 PowersShell 5 开始,有一个Compress-Archivecmdlet 可以立即完成任务。

回答by noam

This compresses .\in contents to .\out.zip with System.IO.Packaging.ZipPackage following the example here

这将使用 System.IO.Packaging.ZipPackage 将 .\in 内容压缩到 .\out.zip,遵循此处的示例

$zipArchive = $pwd.path + "\out.zip"
[System.Reflection.Assembly]::Load("WindowsBase,Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")
$ZipPackage=[System.IO.Packaging.ZipPackage]::Open($zipArchive, [System.IO.FileMode]"OpenOrCreate", [System.IO.FileAccess]"ReadWrite")
$in = gci .\in | select -expand fullName
[array]$files = $in -replace "C:","" -replace "\","/"
ForEach ($file In $files) {
   $partName=New-Object System.Uri($file, [System.UriKind]"Relative")
   $part=$ZipPackage.CreatePart($partName, "application/zip", [System.IO.Packaging.CompressionOption]"Maximum")
   $bytes=[System.IO.File]::ReadAllBytes($file)
   $stream=$part.GetStream()
   $stream.Write($bytes, 0, $bytes.Length)
   $stream.Close()
                                                    }
$ZipPackage.Close()

回答by Verts

Used voithos' answer to zip files up in powershell, just had one problem with the Add-Zip function, the Start-sleep -milliseconds 500 caused problems if the file couldn't be fully zipped up in that time -> the next one starting before it was complete caused errors and some files not to be zipped.

使用 voithos 的答案在 powershell 中压缩文件,只是 Add-Zip 功能有一个问题,如果当时无法完全压缩文件,则 Start-sleep -milliseconds 500 会导致问题 -> 下一个开始在它完成之前导致错误和一些文件没有被压缩。

So after playing around for a bit, first trying to get a counter going to check the count of the $zipPackage.Items() and only continuing after the items count increased (which did not work as it would return 0 in some cases when it should not) I found that it will return 0 if the package is still zipping/copying the files up (I think, haha). Added a simple while loop with the start-sleep inside of it, waiting for the zipPackage.Items().count to be a non-zero value before continuing and this seems to solve the problem.

因此,在玩了一会儿之后,首先尝试让计数器检查 $zipPackage.Items() 的计数,并且仅在项目计数增加后才继续(这不起作用,因为在某些情况下它会返回 0不应该)我发现如果包仍在压缩/复制文件,它将返回 0(我认为,哈哈)。添加了一个简单的 while 循环,其中包含 start-sleep,在继续之前等待 zipPackage.Items().count 为非零值,这似乎解决了问题。

function Add-Zip
{
param([string]$zipfilename)

if(-not (test-path($zipfilename)))
{
    set-content $zipfilename ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
    (dir $zipfilename).IsReadOnly = $false  
}

$shellApplication = new-object -com shell.application
$zipPackage = $shellApplication.NameSpace($zipfilename)

foreach($file in $input) 
{ 
        $zipPackage.CopyHere($file.FullName)
        do
        {
            Start-sleep -milliseconds 250
        }
        while ($zipPackage.Items().count -eq 0)
}
}

回答by phani

Using PowerShell Version 3.0:

使用 PowerShell 3.0 版:

Copy-ToZip -File ".\blah" -ZipFile ".\blah.zip" -Force

Hope this helps.

希望这可以帮助。