Automator/Applescript to Rename files when dropped in folder based on parent folder name

When a file is dropped in a folder ( ParentFolder/Folder/File.pdf )

I want to rename the file to ParentFolder_Folder_01.pdf

--Get folder

--Get ParentFolder

--Check for next available number and use it.

If ParentFolder_Folder_01.pdf exists, try _02


I automator, I have chosen folder action

Added 'Get selected finder items'

I have attempted to modify another sript I found here to no avail.


on run {input, parameters}

tell application "Finder"

set theFolder to input as string

set theNameOfFolder to name of folder theFolder

set theFiles to every file in folder theFolder

set theFolders to every folder in folder theFolder

my ProcessFiles(theNameOfFolder, theFiles)

my ProcessFolders(theFolders)

end tell

end run


to ProcessFolders(theFolders)

tell application "Finder"

repeat with thisFolder in theFolders

set theNameOfFolder to name of thisFolder

set theFiles to every file in thisFolder

set theFolders to every folder in thisFolder

my ProcessFiles(theNameOfFolder, theFiles)

my ProcessFolders(thisFolder)

end repeat

end tell

end ProcessFolders


to ProcessFiles(NameOfOuterFolder, theFiles)

tell application "Finder"

repeat with thisFile in theFiles

set theSuffix to my grabSuffixOfFile(name of thisFile)

set name of thisFile to NameOfOuterFolder & "_" & theSuffix

end repeat

end tell

end ProcessFiles


to grabSuffixOfFile(theFile)

set text item delimiters to "_"

return (text item 2 of theFile)

set text item delimiters to ""

end grabSuffixOfFile

iMac, Mac OS X (10.7.2)

Posted on Jan 8, 2012 10:59 PM

Reply
16 replies

Jan 10, 2012 6:49 PM in response to PJJPtx

Normally it is a bad idea to do things with items that are in the attached folder (earlier OS versions will retrigger folder actions when an item is renamed, for example), and you don't need to use a Get Selected Finder Items action since the dropped items are already passed to your workflow (also note that the input items will be a list).


It looks like you are trying to use multiple passes to add on the folder names, but you will have less of a headache if you build the base name and just deal with the number suffix. If I understood your naming scheme correctly, the following script should do the trick - it isn't very fast, but should be OK for a few items at a time.



onrun {input, parameters} -- rename input Finder items (aliases) to name of containing folders



setdividerto"_"-- the divider character between name pieces


setoutputto {} -- the result to pass on to the next action


setcounterto"01"-- start suffix at one



repeatwithanItemintheinput-- step through each item in the input


setanItemtocontentsofanItem-- dereference


tellapplication"Finder"toifclassofitemanItemisdocument filethen-- don't mess with folders or applications


set {itemParent, itemExtension} to {container, name extension} ofanItem


ifitemExtensionisnot""thensetitemExtensionto"." & itemExtension


setgrandParentNametonameofcontainerofitemParent


setparentNametonameofitemParent



setnewNametograndParentName & divider & parentName & divider & counter


setdocumentNamestomygetExistingNames(itemParent)


repeatwhilenewNameisindocumentNames-- increment counter suffix as needed

set counter to text -2 thru -1 of ("0" & (counter + 1))


setnewNametograndParentName & divider & parentName & divider & counter


endrepeat



setnameofanItemto (newName & itemExtension)


setendofoutputtoanItem-- alias still refers to the same file even after renaming


endif


endrepeat



returntheoutput

endrun



togetExistingNames(someFolder) -- get base document names (no extensions) from a folder


setnameListto {}



tellapplication"Finder"torepeatwithaFilein (getdocument filesofsomeFolder)


set {fileName, fileExtension} to {name, name extension} ofaFile


iffileExtensionisnot""thensetfileExtensionto"." & fileExtension


setfileNametotext1thru -((countfileExtension) + 1) offileName-- just the name part


setendofnameListtofileName


endrepeat



returnnameList

endgetExistingNames

Jan 11, 2012 7:37 AM in response to red_menace

You are amazing! Thank you! I am actually using this to keep my personal digital filing cabinet of PDF's in order.

I have another script that takes scanned PDF's from an inbox, OCR's them with Finereader, appends _OCR to the filename and moves them to an OCT_Complete folder. From there, I will review them one by one and drop them into their final folders where they can be renamed. You gave me the final piece to my puzzle. Thanks!


2 questions.

1) If I have GrandParent_Parent_01.pdf, GrandParent_Parent_02.pdf, it renames them all and begins with the next number, in this case being 03. Thoughts on checking for existing matching filenames and skipping?


2) Would I be better off to fire my scripts in this situation based on a time schedule, like once every night, rather than as a folder action?

Jan 11, 2012 8:26 AM in response to P8923J

1) I wrote the script for a folder action, so only new items dropped into a folder would be getting passed to it. If you are doing something like getting the entire contents of a folder that may already have renamed items in it, then you can wrap the renaming part in a test statement to check if items are already renamed, for example:


--


setparentNametonameofitemParent



setnewNametograndParentName & divider & parentName & divider-- base name minus suffix number


if (nameofanItem) does notstart withnewNamethen-- only rename if not already formatted

setnewNametonewName & counter

setdocumentNamestomygetExistingNames(itemParent)

repeatwhilenewNameisindocumentNames-- increment counter suffix as needed

set counter to text -2 thru -1 of ("0" & (counter + 1))

setnewNametograndParentName & divider & parentName & divider & counter

endrepeat


setnameofanItemto (newName & itemExtension)


endif


setendofoutputtoanItem-- alias still refers to the same file even after renaming

--


2) Since the script isn't the speediest thing around, if you wind up dropping a large number of files at one time it may take a while, so in that case the folder action route might work better. With the above modification, it will also work by selecting files or getting the folder contents, so whatever works for your workflow.

Jan 14, 2012 11:00 PM in response to red_menace

here's the new code that seems to work


set this_folder to (choose folder with prompt "Pick the folder containing the images to process:") as string

set divider to "_" -- the divider character between name pieces

set output to {} -- the result to pass on to the next action

set counter to "01" -- start suffix at one


tell application "System Events"

set these_files to every file of folder this_folder whose name ends with "PDF"

end tell


repeat with i from 1 to the count of these_files

set this_file to (item i of these_files as alias)

-- set this_file to contents of this_file -- dereference

tell application "Finder" to if class of item this_file is document file then -- don't mess with folders or applications

set {itemParent, itemExtension} to {container, name extension} of this_file

if itemExtension is not "" then set itemExtension to "." & itemExtension

set grandParentName to name of container of itemParent

set parentName to name of itemParent

set newName to grandParentName & divider & parentName & divider -- base name minus suffix number

if (name of this_file) does not start with newName then -- only rename if not already formatted

set newName to newName & counter

set documentNames to my getExistingNames(itemParent)

repeat while newName is in documentNames -- increment counter suffix as needed

set counter to text -2 thru -1 of ("0" & (counter + 1))

set newName to grandParentName & divider & parentName & divider & counter

end repeat

set name of this_file to (newName & itemExtension)

end if

set end of output to this_file -- alias still refers to the same file even after renaming

end if

end repeat


to getExistingNames(someFolder) -- get base document names (no extensions) from a folder

set nameList to {}

tell application "Finder" to repeat with aFile in (get document files of someFolder)

set {fileName, fileExtension} to {name, name extension} of aFile

if fileExtension is not "" then set fileExtension to "." & fileExtension

set fileName to text 1 thru -((count fileExtension) + 1) of fileName -- just the name part

set end of nameList to fileName

end repeat

return nameList

end getExistingNames


Now I am rename on dropping into the folder with the first script and rename non-conforming files as well. This is very helpful because I sometimes name files GrandParent_Parent_01_notes.pdf

Now, these notes will not get overwritten.


Thanks a ton!

Jan 16, 2013 1:33 PM in response to PJJPtx

hello. Great post. I am working on a small automator-app applscript based that takes in 'droppped on' files...then prompts you to enter the new 'base name' if you will.



I have a version working great, but am having difficulty with making the suffix counter work properly. For instance, if you had 10 files the count should be "001 ... 010" not just "01… 10". The container method as mentioned in this thread it now working in the automator "repeat with f in input" stucture. Any help would be appreciated.



current code:


on run {input, parameters}

set theName to the text returned of (display dialog "Enter Base File Name" default answer "")

set counter to "01"

tell application "Finder"


repeat with f in input

set theExtension to "." & name extension of f

set the name of f to (theName & "_" & counter & theExtension)

set counter to (counter + 1)

end repeat


display dialog "Done!" buttons {"OK"} default button 1 with icon 1


end tell


end run

Jan 16, 2013 1:41 PM in response to mtimmons

to have a three digit index, change this line


set counter to text -2 thru -1 of ("0" & (counter + 1))


to this:


set counter to text -3 thru -1 of ("00" & (counter + 1))


or if you want something generic


set counter to text -digits thru -1 of ("00000000000000" & (counter + 1))


all this line is doing is prefixing the index with a string of zeros, then trimming off the leading zeros to make a string of the correct length.

Jan 16, 2013 2:19 PM in response to mtimmons

well that's what the 'digits' variable is for. e.g.:


set digits to 5

set counter to 3


set counter to text -digits thru -1 of ("00000000000000" & (counter + 1))

--result "00004"


so to make a dynamic version, get the number of files you're trying to convert and use the following (of course, you only need to set digits once, not every time in the loop like this, but for brevity...):


-- get the string length needed based on the string length of the number of files

set digits to (length of (numberOfFiles as text))

set counter to text -digits thru -1 of ("00000000000000" & (counter + 1))

Jan 16, 2013 2:56 PM in response to twtwtw

ah! thank you for the tip. I coded out a count to get the amount of files and got everything working perfeclty. thanks you!


final code:


set theName to the text returned of (display dialog "Enter Base File Name" default answer "")

set counter to "1"

set numberOfFiles to "0"


tell application "Finder"

repeat with f in input

set numberOfFiles to numberOfFiles + 1

end repeat

set digits to ((length of (numberOfFiles as text)) + 1)

repeat with f in input

set itemExtension to name extension of f

if itemExtension is not "" then set itemExtension to "." & itemExtension


set counter to text -digits thru -1 of ("00000000000000" & (counter))

set the name of f to (theName & "_" & counter & itemExtension)

set counter to text -digits thru -1 of ("00000000000000" & (counter + 1))


end repeat


display dialog "Done!" buttons {"OK"} default button 1 with icon 1

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

Automator/Applescript to Rename files when dropped in folder based on parent folder name

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.