从powershell递归归档某种类型的所有文件

问题描述 投票:1回答:1

有没有办法使用Compress-Archive脚本,从路径运行时:

  1. 归档与通配符过滤器匹配的所有文件(例如* .doc)
  2. 将这些文件归档到当前文件夹和所有子文件夹中
  3. 保存相对文件夹结构(使用相对或绝对的选项会很好)

我很难让它同时完成所有这三个。

编辑:

以下过滤器和recurses,但不维护文件夹结构

Get-ChildItem -Path ".\" -Filter "*.docx" -Recurse |
Compress-Archive -CompressionLevel Optimal -DestinationPath "$pwd\doc.archive-$(Get-Date -f yyyyMMdd.hhmmss).zip"

此项目不会递归:

Compress-Archive -Path "$pwd\*.docx" -CompressionLevel Optimal -DestinationPath "$pwd\doc.archive-$(Get-Date -f yyyyMMdd.hhmmss).zip"

在某些时候,我有一个递归而不是过滤的命令,但现在无法回复它。

windows powershell archive compress-archive
1个回答
2
投票

不幸的是,从Windows PowerShell v5.1 / PowerShell Core 6.1.0开始,Compress-Archive非常有限:

  • 保留子目录树的唯一方法是将目录路径传递给Compress-Archive。 不幸的是,这样做不提供包含/排除机制来仅选择文件的子集。 此外,生成的存档将在内部包含一个以输入目录命名的单个根目录(例如,如果将C:\temp\foo传递给Compress-Archive,则生成的存档将包含一个包含输入目录子树的foo目录 - 而不是包含C:\temp\foo的内容。顶层)。 没有保留绝对路径的选项。
  • 一个繁琐的工作是创建目录树的临时副本,只有感兴趣的文件(Copy-Item -Recurse -Filter *.docx . $env:TEMP\tmpDir; Compress-Archive $env:TEMP\tmpDir out.zip - 请注意,将包括空目录。) 鉴于您仍然总是以归档中的输入目录命名的单个根目录结束,即使这可能不适合您 - 请参阅底部的备选方案。

替代方案可能会更好:


Solving the problem with direct use of the .NET v4.5+ [System.IO.Compression.ZipFile] class:

注意:

  • 在Windows PowerShell中,与PowerShell Core不同,您最常使用Add-Type -AssemblyName System.IO.Compression手动加载相关的程序集。
  • 由于PowerShell不支持从Windows PowerShell v5.1 / PowerShell Core 6.1.0开始隐式使用扩展方法,因此您必须明确使用[System.IO.Compression.ZipFileExtensions]类。
# Windows PowerShell: must load assembly System.IO.Compression manually.
Add-Type -AssemblyName System.IO.Compression

# Create the target archive via .NET to provide more control over how files
# are added.
# Make sure that the target file doesn't already exist.
$archive = [System.IO.Compression.ZipFile]::Open(
  "$pwd\doc.archive-$(Get-Date -f yyyyMMdd.hhmmss).zip",
  'Create'
)

# Get the list of files to archive with their relative paths and
# add them to the target archive one by one.
$useAbsolutePaths = $False # Set this to true to use absolute paths instead.
Get-ChildItem -Recurse -Filter *.docx | ForEach-Object {
    # Determine the entry path, i.e., the archive-internal path.
    $entryPath = (
          ($_.FullName -replace ([regex]::Escape($PWD.ProviderPath) + '[/\\]'), ''), 
          $_.FullName
        )[$useAbsolutePaths]
    $null = [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile(
      $archive, 
      $_.FullName, 
      $entryPath
    )
  }

# Close the archive.
$archive.Dispose()
© www.soinside.com 2019 - 2024. All rights reserved.