Renaming Files with a list

I’ve seen a few scripts regarding renaming files, but nothing doing quite what I want.

I have a large number of images which I want to rename with what’s in them. For speeds sake I’ve typed the name in a list rather than the file name itself.

So my script should choose the folder, repeat through the files, take the name from the list, add it to the existing image name then rename the file.

The script below doesn’t do a thing though. I’ll admit I’m rusty as heck with AppleScript.

set nextNameNo to 0
set extension to ".jpg"
set fileFolder to choose folder with prompt "Select Folder" without multiple selections allowed
set nameList to {"Muskmelon", "Horned melon", "Pomelo", "Cantaloupe", "Boysenberry", "Berry", "Grape", "Lime", "Horned melon", "Jujube", "Pear", "Banana", "Date palm", "Lemon", "Prune", "Cantaloupe", "Lychee", "Tangelo", "Jujube", "Lemon", "Cranberry"}

repeat with theCurrentFile in fileFolder
	set nextNameNo to nextNameNo + 1
	set Image to nextNameNo of nameList
	set newname to theCurrentFile & " - " & Image & extension
	tell application "Finder"
		set the name of theCurrentFile to newname
	end tell
end repeat

Welcome to site, tomatediseno.

To help you, you need to clarify - where do you get the list of file names from? Do these names contain the metadata of the jpg file, or do you take them at random?

Here is the beginning of the code (with getting metadata of image file), but to continue we need your explanation:


set theFolder to choose folder with prompt "Select Folder"

-- get the list of JPEG image files in the current folder
tell application "Finder" to ¬
	set jpegFiles to ((every file of theFolder) whose name extension is in {"jpg", "jpeg"}) as alias list

-- if no JPEG images then return, doing nothing
if jpegFiles is {} then return

repeat with jpegFile in jpegFiles -- repeat with the JPEG files in the files list
	-- get metadataList for the current file
	tell application "Image Events"
		set jpegImage to open jpegFile
		set imageMetadataList to metadata tags of jpegImage
	end tell
	-- the rest code            
end repeat

-- RESULT (for the last processed image file):

-- {metadata tag "description" of image "sanyo-vpcsx550.jpg" of application "Image Events", metadata tag "samplesPerPixel" of image "sanyo-vpcsx550.jpg" of application "Image Events", metadata tag "hasAlpha" of image "sanyo-vpcsx550.jpg" of application "Image Events", metadata tag "dpiHeight" of image "sanyo-vpcsx550.jpg" of application "Image Events", metadata tag "dpiWidth" of image "sanyo-vpcsx550.jpg" of application "Image Events", metadata tag "bitsPerSample" of image "sanyo-vpcsx550.jpg" of application "Image Events", metadata tag "profile" of image "sanyo-vpcsx550.jpg" of application "Image Events", metadata tag "formatOptions" of image "sanyo-vpcsx550.jpg" of application "Image Events", metadata tag "ExifColorSpace" of image "sanyo-vpcsx550.jpg" of application "Image Events", metadata tag "pixelHeight" of image "sanyo-vpcsx550.jpg" of application "Image Events", metadata tag "path" of image "sanyo-vpcsx550.jpg" of application "Image Events", metadata tag "creation" of image "sanyo-vpcsx550.jpg" of application "Image Events", metadata tag "software" of image "sanyo-vpcsx550.jpg" of application "Image Events", metadata tag "space" of image "sanyo-vpcsx550.jpg" of application "Image Events", metadata tag "pixelWidth" of image "sanyo-vpcsx550.jpg" of application "Image Events", metadata tag "format" of image "sanyo-vpcsx550.jpg" of application "Image Events", metadata tag "make" of image "sanyo-vpcsx550.jpg" of application "Image Events", metadata tag "model" of image "sanyo-vpcsx550.jpg" of application "Image Events", metadata tag "typeIdentifier" of image "sanyo-vpcsx550.jpg" of application "Image Events"}

There’s no metadata, as I said, I’ve folders of images in alphabetical order. Each item on the list is just a general description of what the image is, or the client, or its purpose.

I look at the image and type what it is: “MDL-Punzones”, “RW-SPA”, “BajaMar-pool-wedding”

The image folder might have “DSC0944.jpg”, “IMG_3821.jpg”, “W1 Outside Aurora - DSC3726.jpg”

So I want to merge them to be

DSC0944 - MDL-Punzones.jpg", “IMG_3821 - RW-SPA.jpg”, “W1 Outside Aurora - DSC3726 - BajaMar-pool-wedding.jpg”

This is so it’s easy to find in any environment. The file name alone tells us exactly what it is.

I could rename the files manually, I simply think it could be easier and faster to just the what I want in each line of a text document and get AppleScript to do the work.

I simply don’t understand what I’m missing or have wrong in my current AppleScript which is preventing it working.

  1. Choose the folder of images.
  2. Going through each image, taking its corresponding name from the list, adding it to the existing name.
  3. Rename the image.

Since you create a list of names manually, there is little point in automating your task.

But if you insist on your script, I will say that there are 3 errors in it:

  1. you confuse the nameList item’s counter with the item itself
  2. you do not sort the resulting list of files in the alphabetical order
  3. you get the file name without extension (that is, the basename) incorrectly.

Try this script instead:


property nameList : {"Muskmelon", "Horned melon", "Pomelo", "Cantaloupe", "Boysenberry", "Berry", "Grape", "Lime", "Horned melon", "Jujube", "Pear", "Banana", "Date palm", "Lemon", "Prune", "Cantaloupe", "Lychee", "Tangelo", "Jujube", "Lemon", "Cranberry"}
property aCounter : 0

set theFolder to choose folder with prompt "Select Folder"

tell application "Finder"
	-- Get files list
	set jpegFiles to ((every file of theFolder) whose name extension is in {"jpg","jpeg"})
	-- Sort the resulting list
	set sortedJpegFiles to (sort jpegFiles by name)
	-- repeat loop with jpeg files in the chosen folder
	repeat with jpegFile in sortedJpegFiles
		set aCounter to aCounter + 1
		-- Get the name and the extension of jpegFile
		set aName to name of jpegFile
		set anExtension to name extension of jpegFile
		-- Get the basename  of the jpegFile
		set ATID to AppleScript's text item delimiters
		set AppleScript's text item delimiters to {"." & anExtension}
		set aBaseName to text item 1 of aName
		set AppleScript's text item delimiters to ATID
		-- Rename the jpegFile
		set aName to aBaseName & "-" & (item aCounter of nameList) & "." & anExtension
		set name of jpegFile to aName
	end repeat
end tell

Thanks, copied and pasted your script but that didn’t do anything, the end result was the same as my script - the file names didn’t change. I appreciate your effort but I don’t think you’re getting what I’m looking for.

Everything is just as I need it, I simply don’t understand why my script didn’t change anything.

The reason for scripting is that renaming each file specifically takes a lot of time, movement and pain from RSI, clicking the file, clicking in the name, waiting for it to become editable, typing, selecting the next file, repeating that thousands of times, it becomes quite painful.

Just opening a text document and dictating the content of each file, a quick search and replace to make it a list then having AppleScript change all the file names.

I used to this sort of thing using MAMP and php, I just thought an AppleScript solution would be more elegant.

Actually, realized what was happening.

The name of the folder was being changed. The files inside were greyed out

set theFiles to every item of (choose file with prompt "Choose Files" with multiple selections allowed) as list

Did the trick.

Thanks for getting me on the right path.

@KniazidisR

Your script works on your system because your files are of kind “JPEG image”.
The ones in my folder have the kind “Image JPEG” so they aren’t treated.
You just missed the fact that kind is a localized property

Would be useful to edit your script this way.

tell application "Finder"
	set kind_loc to localized string "KIND_FORMATTER_1_0" -- ADDED
	-- Get files list
	set jpegFiles to ((every file of theFolder) whose kind is kind_loc) -- EDITED
	-- Sort the resulting list

You may also use an alternate filter which is not localization dependant:

set jpegFiles to ((every file of theFolder) whose name extension is in {"jpg","jpeg"})

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) lundi 24 février 2020 10:03:11

Below are two versions ignoring completely the old Finder.
They are verbose but they are efficient.

----------------------------------------------------------------
use AppleScript version "2.5"
use framework "Foundation"
use scripting additions
----------------------------------------------------------------

property |⌘| : a reference to current application

Germaine()

on Germaine()
	-- define some constants
	set ourSuffix to ".jpg" -- our standardized extension
	set nameList to {"Muskmelon", "Horned melon", "Pomelo", "Cantaloupe", "Boysenberry", "Berry", "Grape", "Lime", "Horned melon", "Jujube", "Pear", "Banana", "Date palm", "Lemon", "Prune", "Cantaloupe", "Lychee", "Tangelo", "Jujube", "Lemon", "Cranberry"}
	set skipsSubdirectoryDescendants to |⌘|'s NSDirectoryEnumerationSkipsSubdirectoryDescendants as integer --> 1
	set skipsPackageDescendants to |⌘|'s NSDirectoryEnumerationSkipsPackageDescendants as integer --> 2
	set skipsHiddenFiles to |⌘|'s NSDirectoryEnumerationSkipsHiddenFiles as integer --> 4
	set theOptions to skipsSubdirectoryDescendants + skipsPackageDescendants + skipsHiddenFiles
	
	set theFolder to choose folder -- default WITHOUT multiple selections
	
	set fileManager to a reference to |⌘|'s NSFileManager's defaultManager()
	
	set keysToRequest to {}
	
	set rootURL to theFolder as «class furl»
	set allURLs to (fileManager's enumeratorAtURL:rootURL includingPropertiesForKeys:keysToRequest options:theOptions errorHandler:(missing value))'s allObjects()
	
	set rootURL to (|⌘|'s NSArray's arrayWithObject:theURL)'s firstObject()
	-- extract the URLs whose extension is jpg or jpeg (ignoring case)
	set theFormat to "(self.pathExtension ==[c] 'jpg') OR (self.pathExtension ==[c] 'jpeg')"
	set thePredicate to |⌘|'s NSPredicate's predicateWithFormat:theFormat
	set theArray to (allURLs's filteredArrayUsingPredicate:thePredicate)
	-- build an array with the file names because, as far as I know, we can't sort NSURL objects
	set theNames to |⌘|'s NSMutableArray's new()
	repeat with aURL in theArray
		(theNames's addObject:(aURL's lastPathComponent()))
	end repeat
	-- sort the array of names
	set theNames to theNames's sortedArrayUsingSelector:"localizedStandardCompare:"
	-- now, a true NSURL is required
	set rootURL to (|⌘|'s NSArray's arrayWithObject:rootURL)'s firstObject()
	set aCounter to 0
	repeat with aName in theNames
		set aCounter to aCounter + 1
		if aCounter > (count nameList) then error "There is too many jpg files in the folder"
		-- drops the original extension
		set nameNoExt to aName's stringByDeletingPathExtension()
		-- build a new name using our standardized extension
		set newName to (nameNoExt as text) & "-" & item aCounter of nameList & ourSuffix
		-- build the complete original URL
		set oldURL to (rootURL's URLByAppendingPathComponent:aName)
		-- build the complete new URL
		set newURL to (rootURL's URLByAppendingPathComponent:newName)
		-- rename the original
		(fileManager's moveItemAtURL:oldURL toURL:newURL |error|:(reference))
	end repeat
end Germaine
----------------------------------------------------------------
use AppleScript version "2.5"
use framework "Foundation"
use scripting additions
----------------------------------------------------------------

property |⌘| : a reference to current application

Germaine()

on Germaine()
	-- define some constants
	set ourSuffix to ".jpg" -- our standardized extension
	set nameList to {"Muskmelon", "Horned melon", "Pomelo", "Cantaloupe", "Boysenberry", "Berry", "Grape", "Lime", "Horned melon", "Jujube", "Pear", "Banana", "Date palm", "Lemon", "Prune", "Cantaloupe", "Lychee", "Tangelo", "Jujube", "Lemon", "Cranberry"}
	set skipsSubdirectoryDescendants to |⌘|'s NSDirectoryEnumerationSkipsSubdirectoryDescendants as integer --> 1
	set skipsPackageDescendants to |⌘|'s NSDirectoryEnumerationSkipsPackageDescendants as integer --> 2
	set skipsHiddenFiles to |⌘|'s NSDirectoryEnumerationSkipsHiddenFiles as integer --> 4
	set theOptions to skipsSubdirectoryDescendants + skipsPackageDescendants + skipsHiddenFiles --> 7
	set keysToRequest to {}
	set fileManager to a reference to |⌘|'s NSFileManager's defaultManager()
	
	set theFolder to choose folder -- default WITHOUT multiple selections
	
	set rootURL to theFolder as «class furl»
	set allURLs to (fileManager's enumeratorAtURL:rootURL includingPropertiesForKeys:keysToRequest options:theOptions errorHandler:(missing value))'s allObjects()
	-- extract the URLs whose extension is jpg or jpeg (ignoring case)
	set theFormat to "(self.pathExtension ==[c] 'jpg') OR (self.pathExtension ==[c] 'jpeg')"
	set thePredicate to |⌘|'s NSPredicate's predicateWithFormat:theFormat
	set ourFiles to (allURLs's filteredArrayUsingPredicate:thePredicate)
	-- as far as I know, we can't sort NSURL objects
	-- so replace every NSURL object by the pointed path
	set ourFiles to |⌘|'s NSMutableArray's arrayWithArray:ourFiles
	set knt to count ourFiles
	repeat knt times
		set aPath to ((ourFiles's item 1)'s |path|())
		(ourFiles's removeObjectAtIndex:0) -- objectAtIndex:0 = item 1 of…
		(ourFiles's addObject:aPath)
	end repeat
	-- Now the array contain paths which we may sort
	set ourFiles to ourFiles's sortedArrayUsingSelector:"localizedStandardCompare:"
	-- now, a true NSURL is required
	set rootURL to (|⌘|'s NSArray's arrayWithObject:rootURL)'s firstObject()
	set aCounter to 0
	repeat with aPath in ourFiles
		set aCounter to aCounter + 1
		if aCounter > (count nameList) then error "There is too many jpg files in the folder"
		-- drops the original extension
		set nameNoExt to (aPath's lastPathComponent())'s stringByDeletingPathExtension()
		-- build a new path using our standardized extension
		set newName to (nameNoExt's stringByAppendingString:("-" & item aCounter of nameList & ourSuffix))
		-- build the complete original URL
		set oldURL to (|⌘|'s NSURL's fileURLWithPath:aPath)
		-- build the complete new URL
		set newURL to (rootURL's URLByAppendingPathComponent:newName)
		-- rename the original
		(fileManager's moveItemAtURL:oldURL toURL:newURL |error|:(reference))
	end repeat
	return true
end Germaine

I really don’t know which is the fastest one.

Is it deliberate that “Cantaloupe” and “Jujube” appear twice in the names list ?

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) lundi 24 février 2020 14:02:05

I tried an alternate format for thr predicate:
set theFormat to “(self.pathExtension IN[c] {‘jpg’, ‘jpeg’})”
but itsn’t ignoring case

No, choose folder is choose folder. So the files should be greyed out and that is right. You should simply choose the container folder of your images. And read some AppleScript book, to get the basic things to continue.

NOTE: I updated my 2 scripts due to a fair amendment from Yvan Koenig. Now it should work for you too.

@KniazidisR

I guess that the OP wished to standardize the extension with the value defined by the instruction:

set extension to “.jpg”

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) lundi 24 février 2020 15:47:21

It’s hard to say exactly what the OP wants. Major solutions have already been shown to him.

But, if we assume that he wants

  1. to get the nameList from a text document,
  2. to standardize all Jpeg images to a single extension “jpg”,

then the following script should be close enough to what he need:


set theTextfile to choose file of type {"txt"} with prompt "Select the Textfile, which contains the Names"
set nameList to paragraphs of (read theTextfile)

set theFolder to choose folder with prompt "Select the Folder, which contains the Jpeg Images"

set countNameList to count nameList
set aCounter to 0

tell application "Finder"
	set kind_loc to localized string "KIND_FORMATTER_1_0"
	return
	-- Get files list
	set jpegFiles to ((every file of theFolder) whose kind is kind_loc)
	-- Sort the resulting list
	set sortedJpegFiles to (sort jpegFiles by name)
	-- repeat loop with jpeg files in the chosen folder
	repeat with jpegFile in sortedJpegFiles
		set aCounter to aCounter + 1
		if aCounter > countNameList then error "There is too many jpg files in the folder"
		-- Get the name and the extension of jpegFile
		set aName to name of jpegFile
		set anExtension to name extension of jpegFile
		-- Get the basename of the jpegFile
		set ATID to AppleScript's text item delimiters
		set AppleScript's text item delimiters to {"." & anExtension}
		set aBaseName to text item 1 of aName
		set AppleScript's text item delimiters to ATID
		-- Rename the jpegFile
		set aName to aBaseName & "-" & (item aCounter of nameList) & ".jpg"
		set name of jpegFile to aName
	end repeat
end tell

NOTE: if the OP want to select only “.jpg” files and not other JPEG image files, the the code line

set jpegFiles to ((every file of theFolder) whose kind is kind_loc)

should be replaced with

set jpegFiles to ((every file of theFolder) whose name extension is "jpg")