[CmdletBinding(SupportsShouldProcess)]param( [string]$SourcePath=".", [string]$SourceSet="*.rar", [switch]$Recurse, [string]$ZipExtension=".zip", [string]$ZipDestPath="./zipped", [string]$ZipOptions="-mm=Deflate -mfb=258 -mpass=15", [string]$MoveProcessedTo="done", [switch]$Flatten, [switch]$Force ) function Get7zExtractCmd { param([string]$ArchivePath,[string]$TmpPath) $local:7zCmd = "7z " if( $Flatten ) { $7zCmd += "e " } else { $7zCmd += "x " } $7zCmd += "-o$(Get-ShellSafePath $TmpPath) $(Get-ShellSafePath $ArchivePath)" $7zCmd } function Get7zCompressCmd { param([string]$ArchivePath),[string]$CompressOptions $local:7zCmd = "7z a -sdel " if( -not $Flatten ) { $7zCmd += "-r " } $7zCmd += "$CompressOptions $(Get-ShellSafePath $ArchivePath)" $7zCmd } # Create a new temporary dir $local:DestPathRoot = Get-Path "$ZipDestPath/" $local:TempPath = Join-Path $DestPathRoot ([System.IO.Path]::GetRandomFileName()) $local:DonePath = [string]::Empty if( $MoveProcessedTo ) { $DonePath = Get-Path $MoveProcessedTo } Write-Verbose "`n`tTempPath: $TempPath;`n`tDestPathRoot: $DestPathRoot;`n`tDonePath: $DonePath" $local:runTimeSpan = [System.Diagnostics.Stopwatch]::StartNew() $local:lastStatus = $runTimeSpan.Elapsed $SourcePath = Get-Path "$SourcePath/" $local:srcSet = Get-ChildItem -Recurse:$Recurse -LiteralPath $SourcePath -Include $SourceSet $local:progress = [ordered]@{ Activity = "ConvertTo-Zip $SourcePath" ItemCount = $srcSet.Count ItemProgress = 0 Elapsed = $runTimeSpan.Elapsed } foreach( $local:srcFile in $srcSet ) { Write-Verbose "Processing $($srcFile.Name)..." $progress.ItemProgress++ $progress.Elapsed = $runTimeSpan.Elapsed if( ($runTimeSpan.Elapsed - $lastStatus).TotalSeconds -gt 3 ) { Show-Progress @progress -Status "Processing $($srcFile.Name)..." } if( Test-Path -LiteralPath $TempPath ) { Remove-Item -Recurse -Force -LiteralPath $TempPath -ErrorAction Stop } $local:relPath = $srcFile.DirectoryName.Replace($SourcePath,[string]::Empty) $local:destPath = $srcFile.DirectoryName.Replace($SourcePath,$DestPathRoot) $local:destZipPath = $(Join-Path $destPath "$($srcFile.BaseName)$ZipExtension") $local:ActionStatus = "Failed" Write-Verbose "Dest: $destZipPath" if( -not $Force -and (Test-Path -LiteralPath $destZipPath) ) { Write-Verbose "Skipping, dest already exists: `"$($destZipPath.Replace($DestPathRoot,[string]::Empty))`"" $ActionStatus = "Skipped" } else { $local:nextCmd = Get7zExtractCmd -ArchivePath $srcFile.FullName -TmpPath $TempPath $null = Invoke-ExpressionEx $nextCmd if( -not (Test-Path -PathType Container -LiteralPath $TempPath) ) { Write-Warning "Failed to convert file:`n`t$($srcFile.FullName)" $ActionStatus = "Failed" } else { Push-Location -LiteralPath $TempPath -ErrorAction Stop $local:destFile = Join-Path $destPath "$([System.io.path]::GetRandomFileName()).zip" $nextCmd = Get7zCompressCmd -ArchivePath $destFile $null = Invoke-ExpressionEx $nextCmd Pop-Location if( -not (Test-Path -LiteralPath $destPath ) ) { New-Item -Type Directory -LiteralPath $destPath } $null = Move-Item -Force:$Force -LiteralPath $destFile $destZipPath $ActionStatus = "Processed" } } if( Test-Path -PathType Container -LiteralPath $TempPath ) { Remove-Item -Recurse -Force -LiteralPath $TempPath } if( $DonePath ) { $local:doneFinalPath = Join-Path $DonePath $relPath if( -not (Test-Path -LiteralPath $doneFinalPath) ) { $null = New-Item -Type Directory $doneFinalPath } $local:moveParams = [ordered]@{ LiteralPath=$srcFile.FullName Destination=$doneFinalPath } if( Test-Path (Join-Path $doneFinalPath $($srcFile.Name))) { $moveParams.Confirm = $true $moveParams.Force = $true } Move-Item @moveParams } [PSCustomObject]([ordered]@{ Action = $ActionStatus SrcMoved = $(if($DonePath){ $true } else {$false}) Path = $relPath File = $srcFile.BaseName }) }