2

Everyday I need create archives of the following

C:.
└───1.Jan
    ├───20000
    │       img1.bmp
    │       img2.bmp
    │       img3.bmp
    │
    ├───20001
    │       img1.bmp
    │       img2.bmp
    │       img3.bmp
    │
    ├───20002
    │       img1.bmp
    │       img2.bmp
    │       img3.bmp
    │
    ├───20003
    │       img1.bmp
    │       img2.bmp
    │       img3.bmp
    │
    ├───20004
    │       img1.bmp
    │       img2.bmp
    │       img3.bmp
    │
    ├───20005
    │        img1.bmp
    │        img2.bmp
    │        img3.bmp
    │
    └───Entered

I currently have the script working with creating the zip files one at a time, However I can sometimes have 200+ folders to zip and they are different sizes so I would like to get this working multithreadded.

function Zip-Folders([String] $FolderPath) {
if ($FolderPath -eq '') {
    return
} 
else {
    $FolderNames = Get-ChildItem -Path $FolderPath -Name -Directory -Exclude Enter*
        foreach ($i in $FolderNames) {
            $TempPath = "$FolderPath\$i"
            $TempFileName = "$i Photos"
            if (-Not(Get-ChildItem -Path $TempPath | Where-Object {$_.Name -like '*.zip'})) {
                Write-Host "[$TempPath] has been compressed to [$TempFileName]."
                Compress-Archive -Path $tempPath\* -DestinationPath $tempPath\$TempFileName
            }
            Else {
                Write-Host "[$i] has already been compressed."
            }
        }
}
}

The code asks for the folder via a Folderbrowser dialog.

If someone could either help with the code or point me in the direction where I can find the information for this, I am a beginner with PowerShell but have done some programming.

If there is any other information needed let me know.

zPRAWN
  • 25
  • 4
  • 3
    If you have the ability to install modules, such as [ThreadJob](https://learn.microsoft.com/en-us/powershell/module/threadjob/?view=powershell-7.1) this is quite easy to do. Another option is to use Runspace however this would require more coding. – Santiago Squarzon Oct 21 '21 at 02:27

1 Answers1

2

This is how you can do it using Runspace, use the -Threshold parameter depending on how many folders you want to compress at the same time.

As commented, it is highly recommended to use the ThreadJob Module if you have the ability to install Modules in your environment.

function Zip-Folders {
    [cmdletbinding()]
    param(
        [ValidateScript({ Test-Path $_ -PathType Container })]
        [Parameter(Mandatory)]
        [String] $FolderPath,

        [int] $Threshold = 10
    )

    begin {
        $RunspacePool = [runspacefactory]::CreateRunspacePool(1, $Threshold)
        $RunspacePool.Open()
        $subFolders = Get-ChildItem -Path $FolderPath -Directory -Exclude Enter*
    }
    
    process {
        try {
            $runspaces = foreach ($folder in $subFolders) {
                $instance = [powershell]::Create().AddScript({
                    param($thisFolder)

                    $fileName = "{0} Photos.zip" -f $thisFolder.Name
                    $absolutePath = $thisFolder.FullName
                    $zipPath = Join-Path $absolutePath -ChildPath $fileName

                    if(-not (Get-ChildItem -Path $absolutePath -Filter *.zip)) {
                        Compress-Archive -Path $absolutePath\* -DestinationPath $zipPath
                        return "[$absolutePath] has been compressed to [$zipPath]."
                    }

                    "[$absolutePath] has already been compressed."
                }).AddParameter('thisFolder', $folder)

                $instance.RunspacePool = $RunspacePool

                [pscustomobject]@{
                    Instance = $instance
                    Handle   = $instance.BeginInvoke()
                }
            }

            foreach($r in $runspaces) {
                $r.Instance.EndInvoke($r.Handle)
                $r.Instance.ForEach('Dispose')
            }
        }
        catch {
            $PSCmdlet.WriteError($_)
        }
        finally {
            $runspaces.ForEach('Clear')
            $RunspacePool.ForEach('Dispose')
        }
    }
}
Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37