从 powershell 递归归档某种类型的所有文件
Archive all files of a certain type recursively from powershell
有没有办法使用 Compress-Archive 脚本,当 运行 来自路径时:
- 归档与通配符过滤器匹配的所有文件(例如 *.doc)
- 在当前文件夹和所有子文件夹中归档此类文件
- 保存相对文件夹结构(不过,使用相对或绝对选项会更好)
我很难同时完成所有这三个。
编辑:
以下过滤器和递归,但不维护文件夹结构
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 v5.1 / PowerShell Core 6.1.0 开始,Compress-Archive
非常有限:
保留子目录树的唯一方法是将 目录路径 传递到 Compress-Archive
.
不幸的是,这样做 没有 inclusion/exclusion 机制仅 select 文件子集。
此外,生成的存档将在内部包含一个以输入目录命名的单根目录(例如,如果您将 C:\temp\foo
传递给 Compress-Archive
,生成的存档将包含单个 foo
目录,其中包含输入目录的子树 - 而不是在顶层包含 C:\temp\foo
的 content ).
没有保留绝对路径的选项。
一个麻烦的解决方法是创建目录树的临时副本,其中只有感兴趣的文件 (Copy-Item -Recurse -Filter *.docx . $env:TEMP\tmpDir; Compress-Archive $env:TEMP\tmpDir out.zip
- 请注意 空 目录将被包括在内)
- 考虑到您最终还是会得到一个以存档内的输入目录命名的根目录,即使这样也可能对您不起作用 - 请参阅底部的备选方案。
备选方案可能会更好:
直接使用 .NET v4.5+ [System.IO.Compression.ZipFile]
and [System.IO.Compression.ZipFileExtensions]
类型。
在 Windows PowerShell 中,与 PowerShell Core (v6+) 不同,您大多数情况下使用 Add-Type -AssemblyName System.IO.Compression.FileSystem
手动加载相关程序集 - 见下文。
使用外部程序,例如7-Zip
直接使用.NET v4.5+解决问题[System.IO.Compression.ZipFile]
class:
注:
在 Windows PowerShell 中,与 PowerShell Core 不同,您大多数情况下使用 Add-Type -AssemblyName System.IO.Compression.FileSystem
.[=28 手动加载相关程序集=]
因为从 Windows PowerShell v5.1 / PowerShell Core 6.1.0 开始,PowerShell 不支持隐式 使用扩展方法,您还必须明确使用 [System.IO.Compression.ZipFileExtensions]
class。
# Windows PowerShell: must load assembly System.IO.Compression.FileSystem manually.
Add-Type -AssemblyName System.IO.Compression.FileSystem
# 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()
有没有办法使用 Compress-Archive 脚本,当 运行 来自路径时:
- 归档与通配符过滤器匹配的所有文件(例如 *.doc)
- 在当前文件夹和所有子文件夹中归档此类文件
- 保存相对文件夹结构(不过,使用相对或绝对选项会更好)
我很难同时完成所有这三个。
编辑:
以下过滤器和递归,但不维护文件夹结构
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 v5.1 / PowerShell Core 6.1.0 开始,Compress-Archive
非常有限:
保留子目录树的唯一方法是将 目录路径 传递到
Compress-Archive
.不幸的是,这样做 没有 inclusion/exclusion 机制仅 select 文件子集。
此外,生成的存档将在内部包含一个以输入目录命名的单根目录(例如,如果您将
C:\temp\foo
传递给Compress-Archive
,生成的存档将包含单个foo
目录,其中包含输入目录的子树 - 而不是在顶层包含C:\temp\foo
的 content ).没有保留绝对路径的选项。
一个麻烦的解决方法是创建目录树的临时副本,其中只有感兴趣的文件 (
Copy-Item -Recurse -Filter *.docx . $env:TEMP\tmpDir; Compress-Archive $env:TEMP\tmpDir out.zip
- 请注意 空 目录将被包括在内)- 考虑到您最终还是会得到一个以存档内的输入目录命名的根目录,即使这样也可能对您不起作用 - 请参阅底部的备选方案。
备选方案可能会更好:
直接使用 .NET v4.5+
[System.IO.Compression.ZipFile]
and[System.IO.Compression.ZipFileExtensions]
类型。
在 Windows PowerShell 中,与 PowerShell Core (v6+) 不同,您大多数情况下使用Add-Type -AssemblyName System.IO.Compression.FileSystem
手动加载相关程序集 - 见下文。使用外部程序,例如7-Zip
直接使用.NET v4.5+解决问题[System.IO.Compression.ZipFile]
class:
注:
在 Windows PowerShell 中,与 PowerShell Core 不同,您大多数情况下使用
Add-Type -AssemblyName System.IO.Compression.FileSystem
.[=28 手动加载相关程序集=]因为从 Windows PowerShell v5.1 / PowerShell Core 6.1.0 开始,PowerShell 不支持隐式 使用扩展方法,您还必须明确使用
[System.IO.Compression.ZipFileExtensions]
class。
# Windows PowerShell: must load assembly System.IO.Compression.FileSystem manually.
Add-Type -AssemblyName System.IO.Compression.FileSystem
# 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()