使用PS将文件夹中的文件压缩为zip文件

时间:2011-04-12 20:20:53

标签: powershell

我有以下脚本将文件夹(文件夹中的所有文件)压缩为zip文件:

 set-content $zipFileName ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18)) 
 $ZipFile = (new-object -com shell.application).NameSpace($zipFileName) 
 Get-ChildItem $folder | foreach {$zipFile.CopyHere($_.fullname)} 

其中$ folder =“C:\ Test”,$ zipFileName =“C:\ data \ test.zip”为例

如果“C:\ Test”不包含空的子文件夹,它可以正常工作,并且它似乎递归地压缩子文件夹中的所有文件。我真的很喜欢上面简单的线条脚本。例如:

C:\Test
   file1.dat
   file2.dat
   Test-Sub
      File21.bat
      ....

但是,我在一个案例中遇到错误。我发现如果有任何空文件夹,例如“C:\ Test \ EmptySub”,

C:\Test
   file1.dat
   file2.dat
   Test-Sub
      File21.bat
      ....
   EmptySub
   AnotherSub
      file31.sp1
      ...

该脚本将生成错误。我尝试了以下脚本:

Get-ChildItem $files -Recurse | foreach { if (!$_.PSIsContainer) 
    {$zipFile.CopyHere($_.fullname)}} 

这不能按预期工作。它只是跳过所有子文件夹。不确定是否有可用于跳过所有空子文件夹的过滤器或子句?

已更新:根据建议,我试了一下。我的问题还没有解决。这是我的问题的更新。首先,我更新了上面的脚本,以显示如何创建$ zipFile对象。其次,我有建议的代码:

Get-ChildItem $files | ? {-not ($_.PSIsContainer -eq $True -and 
  $_.GetFiles().Count -eq 0) } | % {$zipfile.CopyHere($_.fullname)}

我在WindowsXP上尝试了以上更新,它可以正常使用空子文件夹。但是,相同的代码在Windows 2003 Server中不起作用。以下是错误消息:

[窗口标题] 压缩(压缩)文件夹错误

[内容] 找不到文件或没有读取权限。

[确定]

不确定此类型的PK对象是否可以在Windows 2003服务器中运行,或者该对象是否还有其他设置。

3 个答案:

答案 0 :(得分:3)

您可以通过测试get-childitem的空返回来检测空目录。例如,这将返回空目录列表

dir | where{$_.PSIsContainer -and -not (gci $_)}

虽然在你的情况下,你想要反过来:

Get-ChildItem $files | where{-not ($_.PSIsContainer -and -not (gci $_))} | foreach {$zipfile.CopyHere($_.fullname)}} 

答案 1 :(得分:2)

您的代码以递归方式工作,即您获得任何类型的子项(包括文件夹)。如果您打算排除空文件夹,则应过滤它们:

试试这个衬垫:

gci $folder |`
? {-not ($_.PSIsContainer -eq $True -and $_.GetFiles().Count -eq 0) } |`
% {$zipfile.CopyHere($_.fullname)}

答案 2 :(得分:1)

这是我为zip文件创建的函数。您收到读取错误的原因是因为.CopyHere是异步复制过程,因此我的脚本会在继续下一个要压缩的文件之前验证zip文件中是否存在该文件:

function Out-ZipFile ([string]$path) 
{ 
    try
    {
        $files = $input

        if ($path.StartsWith(".\")) { $path=$path.replace(".\","$($pwd)\") }
        if (-not $path.Contains("\")) { $path="$($pwd)\$($path)" }
        if (-not $path.EndsWith('.zip')) {$path += '.zip'} 

        if (-not (test-path $path)) { 
          set-content $path ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18)) 
        } 

        $ZipFile = (new-object -com shell.application).NameSpace($path) 
        $files | % { 
            $FileName = $_.name
            "Adding $FileName to $path"; 
            $ZipFile.CopyHere($_.fullname);  
            While (($ZipFile.Items() | where { $_.Name -like $FileName }).Size -lt 1) { Start-Sleep -m 100 };
        } 
    }
    catch
    {
        write-output "Error Encountered: `n$_"
        return $_
        throw
    }
}