I am using the Expand-Archive
command to unzip some .zip files. I want this process to generate a log and I am trying to use the parameter -PassThru.
Expand-Archive D:\Users\user1\Desktop\Zip\de23.zip -DestinationPath D:\Users\user1\Desktop\result -Force -PassThru
Result:
Expand-Archive : A parameter cannot be found that matches parameter name 'PassThru'.
CodePudding user response:
As mentioned in the comments, the documentation you're referencing is for the latest version of PowerShell. For the last version of Windows PowerShell (version 5.1), the -PassThru
switch is not present.
To work around this you can use the underlying .NET API to "manually" unpack the archive:
Add-Type -AssemblyName System.IO.Compression
$destination = "C:\destination\folder"
# Define log file name
$logFileName = "unpack-archive.log"
# Locate zip file
$zipFile = Get-Item C:\path\to\file.zip
"[$(Get-Date -F o)][INFO] Opening '$($zipFile.FullName)' to expand" |Add-Content $logFileName
# Open a read-only file stream
$zipFileStream = $zipFile.OpenRead()
# Instantiate ZipArchive
$zipArchive = [System.IO.Compression.ZipArchive]::new($zipFileStream)
# Iterate over all entries and pick the ones you like
foreach($entry in $zipArchive.Entries){
try {
"[$(Get-Date -F o)][INFO] Attempting to create '$($entry.Name)' in '${destination}'" |Add-Content $logFileName
# Create new file on disk, open writable stream
$targetFileStream = $(
New-Item -Path $destination -Name $entry.Name -ItemType File
).OpenWrite()
"[$(Get-Date -F o)][INFO] Attempting to copy '$($entry.Name)' to target file" |Add-Content $logFileName
# Open stream to compressed file, copy to new file stream
$entryStream = $entry.Open()
$entryStream.BaseStream.CopyTo($targetFileStream)
}
catch {
"[$(Get-Date -F o)][ERROR] Failed to unpack '$($entry.Name)': ${_}" |Add-Content $logFileName
}
finally {
# Clean up
$targetFileStream,$entryStream |ForEach-Object Dispose
}
}
# Clean up
$zipArchive,$zipFileStream |ForEach-Object Dispose
CodePudding user response:
Complementing Mathias's helpful answer, here is a solution that uses the -Verbose
switch to generate a log and then parses the file paths from this log to achieve the same output as with -PassThru
on newer PowerShell versions:
Expand-Archive ZipFile.zip -DestinationPath C:\ExtractDir -Force -Verbose 4>&1 |
Select-String -Pattern "Created '(. )'" |
Get-Item -Path { $_.Matches.Groups[1].Value }
4>&1
redirects (merges) the verbose stream (created by-Verbose
) into the success (standard output) stream, so we can process it by pipeline commands. See About Output Streams.Select-String
searches each line of output for the given RegEx pattern. See this RegEx101 demo for a detailed explanation and the ability to experiment.- In the
Get-Item
line the path is specified through a delay-bind script block. This script block extracts the value of the 1st group (the file path) from the current RegEx match. Get-Item
outputs aFileInfo
object, similar to whatExpand-Archive -PassThru
on newer PowerShell versions produces. This causes the default PowerShell formatter to produce the familiar directory listing.