Problems with Expand-Archive and Read-Archive (incorrect documentation)

Topics: User Forum
Sep 13, 2014 at 9:18 PM
Edited Sep 13, 2014 at 10:02 PM
Hi,

I was trying to adapt Example 4 from the Expand-Archive documentation for my purposes:
dir x:\ISOs -rec -inc *.iso | Read-Archive | where {$_.path -eq "setup.exe"} | 
extract-archive -path {$_.archivepath} -index (0..19)
The first thing that occured to me was, that the example does not work, even when you replace "extract-archive" (this does not exist, does it?) with "Expand-Archive"

The second thing is, that any reference to $_ seems to be problematic. Here's what I tried first:
Get-ChildItem d:\temp\*.zip | Read-Archive | ? { $_.Path -match "\.(jpg|pdf)$" } | 
Expand-Archive -Path {$_.archivepath}
This gives an error about PS not being able to convert a string into a PscxPathInfo. So I tried:
Get-ChildItem d:\temp\*.zip | Read-Archive | ? { $_.Path -match "\.(jpg|pdf)$" } | 
Expand-Archive -OutputPath d:\temp\dest\
This "works" but it just extracts all files, instead of just the jpg and pdf. What I really would like to have is something like:
Get-ChildItem d:\temp\*.zip | Read-Archive | ? { $_.Path -match "\.(jpg|pdf)$" } | 
% {Expand-Archive -Path { $_.ArchivePath } -OutputPath ("D:\temp\dest\" + ($_.Name -replace "-")) }
... what didn't work in any variation I tried. It just drives me mad that I cannot figure this out. I'd appreciate any help. These commandlets would be really really helpful for me.

[edit] ... and by the way: The Passthru parameter of Expand-Archive doesn't seem to have any effect at all.
Coordinator
Sep 14, 2014 at 2:10 AM
Edited Sep 14, 2014 at 2:12 AM
The issue here is that Read-Archive outputs a generic List (collection) of ArchiveEntry objects to the pipeline - as a single collection. IOW it doesn't pipe each individual object down the pipeline. This means you have to do that manually when you want to filter on individual archive entries. As to why it works that way, I don't know. Perhaps Oisin can tell us.

Here is how to make your scenario work:
C:\PS> Get-ChildItem d:\temp\*.zip | Read-Archive | % GetEnumerator | ? Name -match '\.(jpg|pdf)$' | Expand-Archive -OutputPath d:\temp\dest
HTH,
Keith
Sep 15, 2014 at 2:18 PM
Edited Sep 15, 2014 at 2:24 PM
Yes, that helped! Thanks a lot!

Here's my current - working - solution for my issue:
Get-ChildItem c:\temp\*.zip | Read-Archive | % GetEnumerator | ? Name -match '\.(jpg|pdf)$' | 
% { 
    Expand-Archive -Path $_.ArchivePath -EntryPath $_.Path -OutputPath c:\temp\
    Rename-Item ("c:\temp\" + $_.Name) -NewName ($_.Name -replace "-")
  }
or, even shorter:
Get-ChildItem c:\temp\*.zip | Read-Archive | % GetEnumerator | ? Name -match '\.(jpg|pdf)$' | 
% { 
    Expand-Archive -InputObject $_ -OutputPath c:\temp\
    Rename-Item ("c:\temp\" + $_.Name) -NewName ($_.Name -replace "-")
  }
One question still remains. The docs suggest you can pipe a System.IO.FileSystemInfo for each item to the pipeline, using the -Passthru switch. So, really cool would be this:
Get-ChildItem c:\temp\*.zip | Read-Archive | % GetEnumerator | ? Name -match '\.(jpg|pdf)$' | Expand-Archive -OutputPath c:\temp\ -PassThru | Rename-Item [...]
But it seems that the commandlet does not pipe anyting at all. Is this a bug, or am I missing something?
Coordinator
Sep 15, 2014 at 3:34 PM
Hmm, I don't think the PassThru parameter got implemented. I'll take a look at this tonight. BTW I've fixed the original issue and checked that in.
Nov 19, 2014 at 9:26 AM
JooJanta wrote:
or, even shorter:
or, even shorter:
Get-ChildItem c:\temp\*.zip | (Read-Archive) | ? Name -match '\.(jpg|pdf)$' | 
% { 
    Expand-Archive -InputObject $_ -OutputPath c:\temp\
    Rename-Item ("c:\temp\" + $_.Name) -NewName ($_.Name -replace "-")
  }
Coordinator
Nov 19, 2014 at 4:44 PM
3.2 no longer requires the call to GetEnumerator but 3.1 did.
Nov 19, 2014 at 5:20 PM
... and -PassThru works in 3.2!

Thanks a lot!

PS: maximvm, (Read-Archive) - with the brackets - results in an error on my system (expressions only allowed as first element in pipeline or so). Without brackets it's working.
Coordinator
Nov 19, 2014 at 5:28 PM
@JooJanta Can you verify that the -PassThru parameter on Expand-Archive is or is not working as you would expect?

There is a call to change the current behavior of passing through the "input" object to Expand-Archive. The suggested change is to make -PassThru output each "expanded" Directory and File instead of the object that was input to Expand-Archive. I believe this would break your rename scenario but you could work around that by using -PipelineVariable.
Nov 19, 2014 at 5:29 PM
Just tried -PassThru and contrary to the help info Expand-Archive returns Pscx.Commands.IO.Compression.ArchiveReader.ArchiveEntry objects. Wouldn't it be more logical to return FileSystemInfo object(s) (FileInfo/DirectoryInfo) objects pointing to the extracted files?
Nov 19, 2014 at 5:39 PM
@r_keith_hill I wrote my last post at the same time as you posted :)

So yes, I would second the suggestion to output expanded directories/files to the pipeline. Seems more plausible to me. Actually I had that in mind when I posted my rename example.
Nov 19, 2014 at 9:16 PM
JooJanta wrote:
PS: maximvm, (Read-Archive) - with the brackets - results in an error on my system (expressions only allowed as first element in pipeline or so). Without brackets it's working.
oops. sorry.
(Read-Archive $_ ) should work.
i use construction like this:
$files = gci *.zip
(Read-Archive $files) | where .... blah-blah-blah
but anyway - as mentioned by r_keith_hill you don't need it anymore starting from 3.2.0 release!