使用PowerShell提取zip文件时放弃目录结构



换句话说,PowerShell的Expand-Archive是否等同于unzip-j命令行参数?如果没有,在Windows上是否有替代?

我试过Expand-Archive -Path thing.zip -DestinationPath "somepath" -Force,它只是把目录结构放在另一个名为somepath的文件夹中。

这个函数将做你想做的,显然处理可能的文件冲突没有实现,取决于你想如何实现。目前,如果一个同名的文件已经存在,它会给你一个错误并跳过它。这个函数是这个答案的简化版本,它实际上保留了文件夹结构。

如果没有参数传递给-DestinationPath参数,zip条目将被提取到当前位置。

using namespace System.IO
using namespace System.IO.Compression
function Expand-ZipArchive {
[CmdletBinding(DefaultParameterSetName = 'Path')]
param(
[Parameter(ParameterSetName = 'Path', Mandatory, Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName)]
[string] $Path,
[Parameter(ParameterSetName = 'LiteralPath', Mandatory, ValueFromPipelineByPropertyName)]
[Alias('PSPath')]
[string] $LiteralPath,
[Parameter()]
[string] $DestinationPath
)
begin {
Add-Type -AssemblyName System.IO.Compression
$DestinationPath = $PSCmdlet.GetUnresolvedProviderPathFromPSPath($DestinationPath)
}
process {
$arguments = switch($PSCmdlet.ParameterSetName) {
Path { $Path, $false, $false }
LiteralPath { $LiteralPath, $false, $true }
}
$null = [Directory]::CreateDirectory($DestinationPath)
foreach($item in $ExecutionContext.InvokeProvider.Item.Get.Invoke($arguments)) {
try {
$fileStream = $item.Open([FileMode]::Open)
$zipArchive = [ZipArchive]::new($fileStream, [ZipArchiveMode]::Read)
foreach($entry in $zipArchive.Entries) {
try {
# if it's a folder, exclude it
if(-not $entry.Name) {
continue
}
$path = [Path]::Combine($DestinationPath, $entry.Name)
# will throw if a file with same name exists, intended
# error handling should be implemented in `catch` block
$fs   = [FileStream]::new($path, [FileMode]::CreateNew)
$wrappedStream = $entry.Open()
$wrappedStream.CopyTo($fs)
}
catch {
$PSCmdlet.WriteError($_)
}
finally {
$fs, $wrappedStream | ForEach-Object Dispose
}
}
}
catch {
$PSCmdlet.WriteError($_)
}
finally {
$zipArchive, $fileStream | ForEach-Object Dispose
}
}
}
}
Expand-ZipArchive .myZip.zip

作为一种仅限powershell的方法,您可以将归档文件解压缩到临时目录,然后将文件移动到最终位置,从而丢弃目录结构。

$archiveName = 'test.zip'
$destination = 'test'
# Create temp path as a sub directory of actual destination path, so the files don't 
# need to be moved (potentially) across drives.
$destinationTemp = Join-Path $destination "~$((New-Guid).ToString('n'))"
# Create temp directory
$null = New-Item $destinationTemp -ItemType Directory
# Extract to temp dir
Expand-Archive $archiveName -DestinationPath $destinationTemp
# Move files from temp dir to actual destination, discarding directory structure
Get-ChildItem $destinationTemp -File -Recurse | Move-Item -Destination $destination
# Remove temp dir
Remove-Item $destinationTemp -Recurse -Force

WithPowerShell 7+,您甚至可以在提取后立即移动每个文件,使用Expand-Archive:

的新-PassThru开关
$archiveName = 'test.zip'
$destination = 'test'
# Create temp path as a sub directory of actual destination path, so the files don't 
# need to be moved (potentially) across drives.
$destinationTemp = Join-Path $destination "~$((New-Guid).ToString('n'))"
# Create temp directory
$null = New-Item $destinationTemp -ItemType Directory
# Expand to temp dir and move to final destination, discarding directory structure
Expand-Archive $archiveName -DestinationPath $destinationTemp -PassThru | 
Where-Object -not PSIsContainer | Move-Item -Destination $destination
# Remove temp dir
Remove-Item $destinationTemp -Recurse -Force

最新更新