# Rename jpg images using a script

I like to collect images for my desktop background, the problem is sometimes the image names don't represent what the image is. I decided to write a script that reads a text file that contains the source of the images to be renamed, and the base name. The script renames the images using the base name and increment counter and moves it to a portable drive.

Picture Database:

Pictures\Landscape,landscape
Pictures\Batman,batman


Script:

$picture_database_location = "$PSScriptRoot\pictures_database.txt"
$filter_ext = "jpg"$rootDestination = "R:"

function determineIfFileorDirectoryExists
{    Param([string]$fileordirectory) <# Determine if a File or Directory Exists. If the file or directory doesn't exists, it will throw an exception. Args: string:$fileordirectory - the variable that contains the file or directory
we're going to Test.

Returns:
None
#>

$fileordirectoryExists = Test-Path$fileordirectory

if($fileordirectoryExists -eq$false){
throw [System.IO.DirectoryNotFoundException] "Not Found: $fileordirectory" } } function determineargumentCount { Param([string[]]$arraytoverify)

<#
Determines if the array length is correct. If not, it will throw and display the elements in the array.

Args:
string[]: $arraytoverify - the array to check for length. Return: None #> if ($arraytoverify.Length -ne 2){
throw "Argument count incorrect. # of Parameters: $arraytoverify.Length. nProvided Parameters:$arraytoverify"
}
}

try{

# Before renaming any images we need to verify that the source location and destination exist.
determineIfFileorDirectoryExists -fileordirectory "$picture_database_location" determineIfFileorDirectoryExists -fileordirectory "$rootDestination"
$picture_database = Get-Content$picture_database_location

ForEach ($image in$picture_database){
# Construct an array based on the split string
# $imagaeArray is constructed as follows: #$imageArray[0]: The directory that contains the images to rename
# $imageArray[1]: The base name to rename the images$imageArray = $image.Split(",") determineargumentCount -arraytoverify$imageArray
# Construct the Source path with USERPROFILE environment variable and the first element in the array (the directory that contains our pictures)
$imagePath = Join-Path$env:USERPROFILE -ChildPath $imageArray[0] determineIfFileorDirectoryExists -fileordirectory "$imagePath"
Set-Location -Path "$imagePath" # Filter images by type and bulid a list with all the image names$fileList = (Get-ChildItem $imagePath -Filter "*.jpg").Name if($fileList.Length -gt 0){

# Construct a string representing the desination path
$DestinationPath = Join-Path$rootDestination -ChildPath $imageArray[0]$doesDirectoryExist = Test-Path $DestinationPath if($doesDirectoryExist -eq $false){ # - ErrorAction Stop - stops the script if the action take fails. md "$DestinationPath" -ErrorAction Stop
determineIfFileorDirectoryExists -fileordirectory "$DestinationPath" } # Get the number of pictures in the destionation and set the counter. [int]$fileCounter = (Get-ChildItem $DestinationPath -Filter "*.jpg").Length ForEach ($imagetoRename in $fileList){$fileCounter++
$renamed_file = "{0}_{1}.{2}" -f$imageArray[1],$fileCounter,$filter_ext
$imageDestination = Join-Path$DestinationPath -ChildPath $renamed_file Write-Output "Image : {0} will be renamed to {1}" -f$imagetoRename, $imageDestination Move-Item -Path "$imagetoRename" -Destination "$imageDestination" } } } Set-Location$PSScriptRoot
}

catch [System.IO.DirectoryNotFoundException]
{
Write-Output $PSItem.Exception.Message } catch [System.IO.IOException] { Write-Output$PSItem.Exception.Message
}

catch{
Write-Output $PSItem.Exception.Message } finally{ exit }  Suppose there were two images in each of the source folders, it will rename them like this: landscape_1.jpg landscape_2.jpg batman_1.jpg batman_2.jpg  Areas of Concern: • I use the variable $imageArray but I'm thinking simple classes might make it more readable instead of a bulky comment.
• I'm aware a nested for loop isn't good for performance, but I'm unsure how to rewrite the code.
• Nice first question. I hope you get good answers. Jul 21 '18 at 15:33
• One style thing that I like to do is that you can turn test-paths into one-liners. if(test-path $path) and negated being if(!(test-path$path)) because it returns a bool Jul 25 '18 at 0:22

I would use a csv to store the elements and use Import-Csv to read data in.
I have a small problem with the assumption that the Picture folder is always a sub-folder of $Env:USERPROFILE as this special folder could be relocated. The proper way to evaluate the pictures folder location of the currently logged on user is: [Environment]::GetFolderPath('MyPictures')  If you structure your comment block in the functions with some keywords this can be used by Get-Help <# .SYNOPSIS .DESCRIPTION .EXAMPLE .PARAMETER .INPUTS .OUTPUTS .NOTES .LINK #>  See the link for an advanced function template I see no problem with stacked for, I'd use a ForEach ($file in $fileList){...}  to enumerate the $fileList` collection.