I have a nested folder structure for example like this (it's a lot more for simplicity I put an example)
- folder1
- folderA
a.zip
- folderB
b.zip
I want to unzip all zip files in same folder and delete the original zip file.
so my expected output is like
- folder1
- folderA
- a
files in a.zip
- folderB
- b
files in b.zip
I can get list of all zip files by Get-ChildItem '.' -R -Filter *.zip command
Then also I can pipe it to unzip like
Get-ChildItem '.' -R -Filter *.zip | Expand-Archive -Force -DestinationPath c:\a
which giving a fixed destination path Also I can able to get the folder name of each zip file by
Get-ChildItem '.' -R -Filter *.zip | select -ExpandProperty DirectoryName
also I tried
Get-ChildItem '.' -R -Filter *.zip | Expand-Archive -Force -DestinationPath $_.DirectoryName
and
Get-ChildItem '.' -R -Filter *.zip | Expand-Archive -Force -DestinationPath %{$_.DirectoryName}
also
Get-ChildItem '.' -R -Filter *.zip | Expand-Archive -Force -DestinationPath {$_.DirectoryName}
But I can't find a way to pass the DirectoryName to Expand-Archive command
CodePudding user response:
I found the solution in case someone else has same issue
Get-ChildItem '.' -R -Filter *.zip | ForEach-Object {
Expand-Archive $_.FullName "$($_.DirectoryName)/$($_.Basename)" -Force
Remove-Item $_.FullName
}
CodePudding user response:
You can call the Directory property of the FileInfo objects outputted by Get-ChildItem to get the DirectoryInfo object of the parent folder of these files, then you can call the FullName property of the parents to get the destination folder.
In theory, this could work using -PipelineVariable instead of a ForEach-Object loop but I haven't personally tested it.
$ErrorActionPreference = 'Stop'
Get-ChildItem '.' -R -Filter *.zip | ForEach-Object {
try {
Expand-Archive -LiteralPath $_.FullName -DestinationPath $_.Directory.FullName -Force
Remove-Item -LiteralPath $_.FullName
}
catch {
Write-Warning $_.Exception.Message
}
}
