-1

I want to move all images in a directory, including subdirectories, to a new location while maintaining the existing folder structure.

Following the example, here, I put the objects into a variable, like so:

$picMetadata = Get-FileMetaData -folder (Get-childitem K:\myImages -Recurse -Directory).FullName

The move must be based on the results of a logical expression, such as the following for example.

foreach ($test01 in $picMetadata)  { 
 if ($test01.Height -match "^[0-9]?[0-9] ") { 
 Write-Host "Test01.Height:" $test01.Height 
} 
}

Still at an early testing phase So far, I'm having no success even testing for the desired files. In the example above, I thought this simple regex test might provide for anything from "1 pixels" to "99 pixels", which would at least slim down my pictures collection (e.g. an expression without the caret, like "[0-9][0-9] " will return "NN pixels" as well as "NNN Pixels", "NNNNNN pixels", etc.)

Once I figure out how to find my desired images based on a logical, image object dimensions test, I will then need to create a script to move the files. Robocopy /MOV would be nice, but i'm probably in over my head already.

I was going to try to base it on this example (which was provided to a User attempting to COPY (not move / copy/delete) *.extension files). Unfortunately, such a simple operation will not benefit me, as I wish to move .jpg,.png,.gif, etc, based on dimensions not file extension:

$sourceDir = 'K:\myImages\'
$targetDir = ' K:\myImages_psMoveTest\'

Get-ChildItem $sourceDir -filter "*" -recurse | `
    foreach{
        $targetFile = $targetDir + $_.FullName.SubString($sourceDir.Length);
        New-Item -ItemType File -Path $targetFile -Force;
        Copy-Item $_.FullName -destination $targetFile
    }

Perhaps you have a powershell script that could be used for my intended purpose? I'm just trying to move smaller images out of my collection, without having to overwrite same name images, and lose folder structure, etc.

Thank you very much for reading, and any advisory!

(Edit: Never opposed to improving Powershell skill, if you are aware of a freeware software which would perform this operation, please advise.)

J S
  • 1
  • 2

1 Answers1

0

If I understand your question correctly, you want to move image files with a pixel height of 1 up to 99 pixels to a new destination folder, while leaving the subfolder structure intact.

If that is true, you can do:

# needed to use System.Drawing.Image
Add-Type -AssemblyName System.Drawing

$sourceDir = 'K:\myImages'
$targetDir = 'K:\myImages_psMoveTest'

Get-ChildItem $sourceDir -File -Recurse | ForEach-Object {
    $file = $_.FullName   # need this for when we hit the catch block
    try {
        # Open image file to determine the pixelheight
        $img    = [System.Drawing.Image]::FromFile($_.FullName)
        $height = $img.Height
        # dispose of the image to remove the reference to the file
        $img.Dispose()
        $img = $null
        if ($height -ge 1 -and $height -le 99) {
            $targetFolder = Join-Path -Path $targetDir -ChildPath $_.DirectoryName.Substring($sourceDir.Length)
            # create the target (sub) folder if it does not already exist
            $null = New-Item -Path $targetFolder  -ItemType Directory -Force
            # next move the file
            $_ | Move-Item -Destination $targetFolder -ErrorAction Stop
        }
    }
    catch {
        Write-Warning "Error moving file '$file': $($_.Exception.Message)"
    }
}
Theo
  • 57,719
  • 8
  • 24
  • 41
  • This is VERY close to what I want. But, it is copying the files without removing the originals. Perhaps it's a permissions issue? PS Output: `Move-Item : The process cannot access the file because it is being used by another process. At line:11 char:18 + $_ | Move-Item -Destination $targetFolder + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : WriteError: (K:\myImages_rob...ap\wordwrap.ico:FileInfo) [Move-Item], IOException + FullyQualifiedErrorId : MoveFileInfoItemIOError,Microsoft.PowerShell.Commands.MoveItemCommand` – J S Feb 18 '22 at 03:24
  • @JS Ah, yes. Please see my edit. The `$img` kept a reference to the file, so you couldn't move it. Changed that now to dispose of the image as soon as we have determined the pixel height. – Theo Feb 18 '22 at 09:51
  • Thank you! Seems it's not doing anything with the files now... no subdirs created in new folder; no imgs copied. The PS out for all files: `WARNING: K:\myImages_120x120\a_d_i_justWords(v1.2)48p.jpg is not an image WARNING: K:\myImages_120x120\a_d_i_logo_CROPPED20px.png is not an image` (etc.) seems it thinks none are imgs. i must study the code. I'm sure your edit is nearly there. I'm not familiar enough with Powershell scripting to know where to begin yet. I welcome any further revisions/ advisory. I do look forward to more feedback. – J S Feb 19 '22 at 04:07
  • @JS Ok, the reference to the file was a bit tougher than I expected.. I have added `$img = $null` to really get rid of it so we can move the file. I also changed the message in the catch block so when something goes wrong, you will get a better description of the actual error. – Theo Feb 19 '22 at 09:54