Home > OS >  Create an exe script to select and move all images on my computer
Create an exe script to select and move all images on my computer

Time:12-27

This PowerShell script is intended to copy photos from one or more source directories to a destination directory, organizing them by image type (JPEG, PNG, BMP, and HEIC).

It asks the user to enter the paths of the source directories and the source directories to exclude, as well as the path of the destination directory. These paths are stored in the variables $sources, $excluded, and $destination, respectively.

The script then converts the string contained in $sources into an array using the -split instruction, which allows for splitting a string based on a specified separator (here, a comma). If the user did not specify any source directories to exclude, the $excluded variable is initialized to an empty array using the Where-Object instruction.

The path of the destination directory is added to the $excluded array in order to avoid copying the photos to the destination directory itself.

The script then checks if the destination directory exists, and creates it if it does not using the New-Item instruction. It also creates destination directories for each file type (JPEG, PNG, BMP, and HEIC).

Finally, the script searches the computer's file system for files and copies the found photos to the destination directories according to their extension. It uses the Get-ChildItem instruction to retrieve the files in the source directories and the Copy-Item command to copy these files to the destination directories. The Where-Object clause is used to verify that the file is not in one of the excluded source directories.

$sources = Read-Host "Please enter the paths of the source directories (separated by commas) :"

$excluded = Read-Host "Please enter the paths of the source directories to exclude (separated by commas) :"

$destination = Read-Host "Please enter the path of the destination directory :"

$sources = $sources -split ","

$excluded = $excluded -split "," | Where-Object {$_}

$excluded  = $destination

if (!(Test-Path $destination)) { New-Item -ItemType Directory -Path $destination }

"JPG", "PNG", "BMP", "HEIC" | ForEach-Object { New-Item -ItemType Directory -Path "$destination\$_" }

foreach ($source in $sources) {
    if ($excluded -notcontains $source) {
        "jpg", "png", "bmp", "heic" | ForEach-Object {
            $extension = $_.ToUpper()
            Get-ChildItem -Recurse $source -Filter "*.$_" | Where-Object {$_.Directory.FullName -notcontains $excluded} | Copy-Item -Destination "$destination\$extension"
        }
    }
}

This script works very well except that it still adds the photos of the excluded folders! Why ?

CodePudding user response:

I would use a regex for this to exclude the folders. Also I'd use Group-Object to group the found files by extension, making it easier to copy to the destination folders:

$sources     = Read-Host "Please enter the paths of the source directories (separated by commas) :"
$excluded    = Read-Host "Please enter the paths of the source directories to exclude (separated by commas) :"
$destination = Read-Host "Please enter the path of the destination directory :"

$sources  = @($sources -split "," | Where-Object {$_ -match '\S'}).Trim()
$excluded = @($excluded -split "," | Where-Object {$_ -match '\S'}).Trim()   $destination

# create a regex of the folders to exclude
# each folder will be Regex Escaped and joined together with the OR symbol '|'
$notThese = ($excluded | ForEach-Object { [Regex]::Escape($_) }) -join '|'

# enumerate the paths for the specified files
Get-ChildItem -Path $sources -Recurse -File -Include "*.JPG", "*.PNG", "*.BMP", "*.HEIC" |
Where-Object{ $_.DirectoryName -notmatch $notThese } | 
Group-Object Extension |
ForEach-Object {
    $targetPath = Join-Path -Path $Destination -ChildPath $_.Name.TrimStart(".").ToUpper()
    # create the target path if this does not already exist
    $null = New-Item -Path $targetPath -ItemType Directory -Force
    # next copy the files in this group
    $_.Group | Copy-Item -Destination $targetPath -Force
}

CodePudding user response:

Replace:

$_.Directory.FullName -notcontains $excluded

with the following, which reverses the operands passed to the -notcontains operator:

$excluded -notcontains $_.Directory.FullName

Alternatively, use the related -notin operator:

$_.Directory.FullName -notin $excluded

Both -contains / -notcontains and -in / -notin test an array (collection) for containing a scalar (single object), through element-by-element equality testing. They only differ by the order of operands:

# -contains / -notcontains: array is the *LHS* (left-hand side) operand
@(1, 2, 3) -contains 2 # -> $true

# -in / -notin: array is the *RHS* (right-hand side)
2 -in @(1, 2, 3) # -> $true
  • Related