This is amazing!!! I tried out a few scenarios with duplicates and love this.
One final curveball that could really make things crazy… Every once in a while (I am renaming images) there are multiple images of a single item. The main image has the _main and the secondary images are named as _alt_1, _alt_2 etc. I am going to try adding in an IF statement that would at least label these images in yellow and leave them in the folder while copying the rest. In a perfect world the script would read the original names and if an image has “_alt” in the name it would rename this image the same as the “_main” and keep them associated and then move on to the next image.
I.E.
im6035083_main.jpg im6035086_main.jpg
im6035086_alt_1.jpg
im6035089_main.jpg
renames and maintains the _alt_1 and uses the same number as the main image without this new name needing to be in the .txt file twice?
Would you feel more comfortable having the numbers with each number on a separate line? It just beats me to be an easier way of entering the number list.
I’ll test the solution thoroughly, so I shall post a solution before this time tomorrow at the latest.
I’ve tried this with the numbers on separate lines but am not having luck as of yet. What delimiter would I use? I’ve tried “¬”. It seems that it definitely prefers the comma separated values, but perhaps there’s a delimiter I’m missing!
Don’t worry, I’ll change the script to handle that.
What I wonder is, how are the identical images named originally, before they get the _alt1,_alt2 extension, or do they have that extension already?
OR:
Do you want the “_alt” thing to happen upon a detection of a file already having that name, as an alternative to skip or overwrite.
I have to know how you think it should be incoroporated into your work flow.
Personally I think it would be advantageous to have it as both an alternative in the dialog, (which maybe will turn into a list box with alternatives. However, say your images is stored in the original folder with the same name, and say a number after them, like file, file 1, file 2, file 3 and so on, then it is very easy to graft out all the file names for a batch which corresponds to one single number in your list. (I’ll sort the list by filenames, and any filenames with the same original names in the destination folder will be bluntly overwritten during the duplication phase).
Having it as an alterntative during the renaming after the duplication is very hard, and error prone, as I then have to know which “_alt number” the file is going to represent if not just the next higher, but I foresee this to be a messy and not so practical approach.
I understand you to state that under this approach, the original files that there are more than one of will already have the suffix _main or _alt?
How about the files that only come in a quantity of one? Will all of those have the extension of _main already, or is that still a job for the script. (It’s no problem, I only have to figure out how it should work.)
Sorry I completely missed a great portion of your response!
All files come with the designation as _main, _alt_1, _alt_2 … Those with a main image and alternate images have the same #. Below is a view of how the files are named before the renaming happens. Post rename all files should maintain the same format of prefix/suffix with a new number replacing the old. Those with multiple images as alts should repeat the same new number to keep them organized and associated with their _main file. The trick is that these numbers that repeat are not repeated in the .txt file of new numbers, the script must recognize which files have alts and repeat the same new number for as many alts as each file has and then move on to the next new number for the next file with a _main. Let me know if it’s still unclear and as always, HUGE THANKS!
Example Original List:
im6476249_main.jpg
im6476252_main.jpg im6476255_main.jpg
im6476255_alt_1.jpg
im6476255_alt_2.jpg
im6476258_main.jpg im6476261_main.jpg
im6476261_alt_1.jpg
im6476264_main.jpg
Example Output List Post Script:
im1234567_main.jpg
im1234568_main.jpg im1234569_main.jpg
im1234569_alt_1.jpg
im1234569_alt_2.jpg
im1234570_main.jpg im1234571_main.jpg
im1234571_alt_1.jpg
im1234572_main.jpg
Thanks! In the mean time is there a way to update my applescript? After some searching and doing all normal updates on my computer I’ve hit a wall. The current script in #20 does not compile for me currently.
Just remove the use clauses at top, and change display notification into display alert, (you must remove the subtitle predicate and the subtitle itself too.)
Here is the new version. There is one thing I am unsure about, so you must check if the pictures keeps their jpg extension (in this case for me, keeps the name extension in general.)
property keepConflicts : false
property scriptTitle : "Duplicate and Rename in DestFolder"
property lastLoc : missing value
if lastLoc is missing value then set lastLoc to path to desktop folder
tell application (path to frontmost application as text)
set sourceFolder to choose folder with prompt "Original Images" default location lastLoc
set lastLoc to sourceFolder
set destFolder to choose folder with prompt "Rename Destination" default location sourceFolder
set NewNames to choose file with prompt ".TXT file of new names" default location (path to desktop folder)
end tell
duplicateAndRenumber(sourceFolder, destFolder, NewNames)
on duplicateAndRenumber(sourceFolder, destFolder, NewNames)
set {overWriteAll, skipAll, haveAsked, movedCount} to {false, false, false, 0}
try
set thetext to read NewNames as «class utf8»
set theList to compactList for (flattenTable for (explode from thetext by ","))
set thePrefix to "im"
set theMainSuffix to "_main"
set theAltSuffix to "_alt_"
tell application "Finder"
set theItems to (sort (duplicate files of folder sourceFolder to folder destFolder with replacing) by name) as alias list
script o
property l : theItems
property newNum : theList
property justNameTable : {}
end script
set renameCount to (count theItems)
repeat 1 times
local n
set n to {}
repeat with i from 1 to renameCount
set end of n to name of item i of o's l
end repeat
set o's justNameTable to makeHelperTable of me for n
-- We have to rearrange the ordering of stuff, as our semantics
-- doesn't coincide with lexical sorting.
set i to 1
repeat
if (count item i of o's justNameTable) = 3 then
local next
set next to i + 1
repeat
if (count item next of o's justNameTable) = 3 then
set next to next + 1
else
exit repeat
end if
end repeat
-- the last shall be the first!
local tmpNameHolder, tmpAliasHolder
set {tmpNameHolder, tmpAliasHolder} to {item next of o's justNameTable, item next of o's l}
set {item next of o's justNameTable, item next of o's l} to {item i of o's justNameTable, item i of o's l}
set {item i of o's justNameTable, item i of o's l} to {tmpNameHolder, tmpAliasHolder}
set i to next + 1
else
set i to i + 1
end if
if i > renameCount then exit repeat
end repeat
end repeat
if (count theList) ≥ (count (uniqueList of me from o's justNameTable by 1)) then
-- it is ok with superfluos numbers in the number list.
-- trenger unique number count here.
set newNumberIDX to 0
repeat with i from 1 to renameCount
if (count item i of o's justNameTable) = 2 then
set newNumberIDX to newNumberIDX + 1
set newName to thePrefix & (item newNumberIDX of o's newNum) & theMainSuffix & "." & item 2 of item i of o's justNameTable
else
set newName to thePrefix & (item newNumberIDX of o's newNum) & theAltSuffix & item 2 of item i of o's justNameTable & "." & item 3 of item i of o's justNameTable
end if
try
if exists file newName of folder destFolder then
if not overWriteAll and not skipAll then
tell me to set btn to button returned of (display dialog ¬
"You have renamed files in this directory already" & return & "The file: " & newName & " exists." & return & "Proceed anyway?" with title my scriptTitle buttons {"No", "Yes to All", "Yes"} with icon 2 default button 3)
if btn = "Yes" or btn = "Yes to All" then
try
move file newName of folder destFolder to trash
set the name of item i of o's l to newName
set movedCount to movedCount + 1
on error
error "An error occured during overwrite of file " & newName
end try
if btn = "Yes to All" then set overWriteAll to true
else if btn = "No" and not haveAsked then -- button = No
tell me to set skipbtn to button returned of (display dialog ¬
"Do you want to skip all files that already exists in dest folder with a new file name?" with title my scriptTitle buttons {"No", "Yes"} with icon 2 default button 2)
if skipbtn = "Yes" then set skipAll to true
set haveAsked to true
if not my keepConflicts then
move item i of o's l to trash
end if
end if
else if overWriteAll then
try
move file newName of folder destFolder to trash
set the name of item i of o's l to newName
set movedCount to movedCount + 1
on error
error "An error occured during overwrite of file " & newName
end try
else if skipAll then
if not my keepConflicts then
move item i of o's l to trash
end if
end if
else
set the name of item i of o's l to newName
set movedCount to movedCount + 1
end if
end try
end repeat
else
error "There were to few numbers for the items"
end if
end tell
tell me to display alert "Duplicated and Renamed " & movedCount & " out of " & renameCount & " Files."
on error e
tell me to display dialog "There was an error:" & e with title "Renaming Files" buttons {"OK"} with icon 2
end try
end duplicateAndRenumber
on uniqueList from table by col
script o
property l : table
end script
set ul to {}
repeat with i from 1 to (count table)
tell item col of item i of o's l
if it is not in ul then ¬
set end of ul to it
end tell
end repeat
return ul
end uniqueList
on makeHelperTable for aList
-- takes filenames on the form "im<number>_main.jpg" or "im<number>_alt_<number>.jpg
-- and forms it into a table for our convenience, when we are renaming a cluster
-- of files that had the same number with the same number.
script o
property l : aList
property m : {}
end script
tell (a reference to text item delimiters)
set {tids, contents} to {contents, {"im", "_main", "_alt_", "."}}
repeat with i from 1 to (count aList)
set end of o's m to compactList of me for (text items of item i of o's l)
end repeat
set contents to tids
end tell
return o's m
end makeHelperTable
on compactList for aList
-- removes any empty list items
set b to aList
script o
property l : aList
end script
repeat with i from 1 to (count aList)
if item i of o's l = "" then set item i of o's l to missing value
end repeat
return o's l's text
end compactList
on flattenTable for aTable
-- turns a table into a single list of values
tell (a reference to text item delimiters)
set {tids, contents} to {contents, return}
set tmpTxt to aTable as text
set aList to text items of tmpTxt
set contents to tids
end tell
return aList
end flattenTable
on explode from theData by aDelim
--takes an initial chunck of text, turns it into paragraphs, and then turns
-- the paragraphs into lists with items. Any leading/trailing single
-- whitespace around the list separator is removed with it.
script o
property theContents : theData
end script
if class of theData is list then
-- we have been broken into paragraphs and must create
-- a list of list for each paragraph.
repeat with i from 1 to (length of o's theContents)
set item i of o's theContents to explode from item i of o's theContents by aDelim
end repeat
else if (offset of linefeed in theData) > 0 ¬
or (offset of return in theData) > 0 then
-- We got an initial chunk of text we'll turn into paragraphs
tell (a reference to text item delimiters)
local tids
set {tids, contents} to {contents, {linefeed, return}}
set o's theContents to text items of o's theContents
set contents to tids
end tell
-- And pass it onto ourself for processing each paragraph.
set o's theContents to explode from o's theContents by aDelim
else
-- We must turn a paragraph into a list of ists.
tell (a reference to text item delimiters)
local tids
set {tids, contents} to {contents, (space & aDelim)}
-- removes any leading spaces from list separator.
set o's theContents to text items of theData
set contents to aDelim
set o's theContents to o's theContents as text
set contents to (aDelim & space)
-- removes any trailing spaces from the list separator.
set o's theContents to text items of theData
set contents to aDelim
set o's theContents to o's theContents as text
-- breaks the string into a list by list separator.
set o's theContents to text items of o's theContents
set contents to tids
end tell
end if
return o's theContents
end explode
I am blown away! This works absolutely perfectly other than it does not keep the .jpg extension currently. In the simpler versions I simply changed the suffix to _main.jpg and this worked great, but now that the _alt suffix is there and is adding the number as it counts the alts I’m in way over my head fixing this on my own!
I was curious, now I know, and have added the .jpg extension to the name, the .jpg may of course be tiff, or img or whatever circumstantial file extension you use. The script is updated.
I’ll advice you to copy the link of this thread and put it on top of your scripts, so that you can find back to it later on, if you have other ideas. And it was a learning experience fo me, as I have been curious about how to implement the skip all stuff in AppleScript.
Just come back if there are more to it, or if you adopt a different workflow.