Batch change filename date format

I am a relative newbie to AppleScript, so thanks in advance for any guidance!

I have a large number of files that were created with filenames in the following format:

(Filename)(space)(date)

with the filename of variable length, and the date consisting of one of the following formats:

Two-digit year
x-x-xx
x-xx-xx
xx-x-xx
xx-xx-xx

Four-digit year
x-x-xxxx
x-xx-xxxx
xx-x-xxxx
xx-xx-xxxx

So, basically, every configuration of one- or two-digit months, one- or two-digit days, and two- or four- digit years. The vast majority are in two-digit year format. Unfortunately, this is the result of adding files over years, and not maintaining consistency. My bad!

I have come up with the following script (at bottom), which allows me to take a x-x-xx date format and convert it to the new format I want, which is:

YYYYMMDD

without hyphens, slashes, etc.

So I have two problems:

  1. I am not sure how to get the individual filename into AppleScript, so I can run this manipulation on that name, then add the new name back to the filename;
  2. I would like to select a group of files and run the script on each consecutively;
  3. (This is likely the hard part) I would like to create variable so that any of the above date formats will be corrected to my new format.

The script:

set the filename to “test 2-7-10”
set theText to text ((offset of “-10” in filename) - 3) through ((offset of “-10” in filename) + 2) in filename
set AppleScript’s text item delimiters to “-”
set thetextitems to text items of theText
set AppleScript’s text item delimiters to {“”}
thetextitems

set theText to item 3 of thetextitems
set myyear to “20” & theText

set theText to item 2 of thetextitems
set mymonth to “0” & theText

set theText to item 1 of thetextitems
set myday to “0” & theText

set theText to myyear & mymonth & myday

set filename to theText

When I run this script on any filename I enter into the script, with the same date format, I get the correct date format. Obviously, if I start with a different date format, I get a bad result.

I greatly appreciate any tips!

Hi,

assuming that
¢ there is always a space character between the base name and the date
¢ the date format is always d[d]-m[m]-yy[yy]

try this, save the script as application bundle,
it works both as applet (double click) or droplet and considers also name extensions


on run
	set chosenFiles to (choose file with multiple selections allowed)
	open chosenFiles
end run

on open droppedItems
	repeat with oneItem in droppedItems
		set {name:Nm, name extension:Ex} to (info for oneItem)
		set filename to text 1 thru ((get offset of "." & Ex in Nm) - 1) of Nm
		if Ex is missing value then set Ex to ""
		if Ex is not "" then set Ex to "." & Ex
		set {TID, text item delimiters} to {text item delimiters, space}
		tell filename to set {theName, theDate} to {(text items 1 thru -2) as text, text item -1}
		set text item delimiters to "-"
		set {dy, mn, yr} to text items of theDate
		set text item delimiters to TID
		if (count yr) = 2 then set yr to "20" & yr
		tell application "Finder" to set name of contents of oneItem to yr & my pad(mn) & my pad(dy) & Ex
	end repeat
end open

on pad(t)
	return text -2 thru -1 of ("0" & t)
end pad

Stefan K-

Thank you very much!

I saved it as an application, then tried dropping a file on it.

The date was converted flawlessly.

I have two questions:

  1. The name of the file was not saved. I did not make my first post clear, I see now. I would like to save the filename and just convert the date portion. For example, convert “test 1-2-09” to “test 20090102”. The script you devised, just replaces the entire file name with “20090102”.

  2. I would prefer to use this as a script. In other words, select a number of files, run the script (I will set up a keyboard shortcut), and have them all converted.

Cheers!

Sorry, I missed to add the filename.
This works with selection


tell application "Finder" to set theSelection to (get selection)
repeat with oneItem in theSelection
	set {name:Nm, name extension:Ex} to (info for oneItem as alias)
	set filename to text 1 thru ((get offset of "." & Ex in Nm) - 1) of Nm
	if Ex is missing value then set Ex to ""
	if Ex is not "" then set Ex to "." & Ex
	set {TID, text item delimiters} to {text item delimiters, space}
	tell filename to set {theName, theDate} to {(text items 1 thru -2) as text, text item -1}
	set text item delimiters to "-"
	set {dy, mn, yr} to text items of theDate
	set text item delimiters to TID
	if (count yr) = 2 then set yr to "20" & yr
	tell application "Finder" to set name of contents of oneItem to theName & space & yr & my pad(mn) & my pad(dy) & Ex
end repeat

on pad(t)
	return text -2 thru -1 of ("0" & t)
end pad

Stefan-

I think I have one part figured out:

tell application "Finder" to set name of contents of oneItem to theName & " " & yr & my pad(mn) & my pad(dy) & Ex

For the line just before “end repeat”

Will this work with all filenames?

Cheers!

Stefan-

I found I was getting the day and month converted incorrectly. so I switched

set {dy, mn, yr} to text items of theDate

to

set {mn, dy, yr} to text items of theDate

And it seems to be working correctly. Thanks!

So I now would like to save it as a script, rather than as an application.

I took the order from your first script


.
set theText to item 3 of thetextitems
set myyear to "20" & theText

set theText to item 2 of thetextitems
set mymonth to "0" & theText

set theText to item 1 of thetextitems
set myday to "0" & theText
.

look at post #4, there is a version with selecting files

Yes, you are correct about the order of ‘mn’ and ‘dy’. I changed the ‘mn’ and ‘dy’ order, and it works great.

And yes, we cross-posted, so I did see your excellent post on using it as a script instead, but only after I was busy trying to modify the script myself, and posting the results.

In Finder, this works great!

But…

I have one more wrinkle (like a good murder mystery).

I am trying to use the script in a program called DevonThink Pro, where the information panel is called up by “shift-command-i”. Thus, the section of the script that uses the info for the file isn’t grabbing the file name. I would just substitute something like:

tell application "system events’ to keystroke “i” using {command down, shift down},

if you think that would work. But I don’t want to mess up the elegance and brevity of your script.

Cheers!

Sorry, I don’t use DevonThink so I have no idea to implement the code into DT.
But AFAIK DevonThink is scriptable

Thank you, sir.

I will fiddle a bit with the script and with DevonThink (you are correct-it is scriptable), and will follow up here when I have an answer.

I got hooked on this, and stayed up soooo late. Alas, to no avail… Now I am tired AND frustrated!

Here is where I am: I tried two different approaches; one was to use keyboard shortcuts to copy and past material from DevonThink (DT) into TextEdit, and one where I tried to get the info directly from DT.

Approach 1: If I open the information window in DT, copy the filename, then paste it into TextEdit:

tell application id "com.devon-technologies.thinkpro2" to set theSelection to (get selection)
repeat with oneItem in theSelection
	tell application "System Events" to keystroke "i" using {command down, shift down}
	delay 0.5
	tell application "System Events" to keystroke "c" using {command down}
	tell application "TextEdit" to activate
	tell application "System Events" to keystroke "n" using {command down}
	set the clipboard to string of (the clipboard as record)
	tell application "System Events" to keystroke "v" using {command down}
	delay 2
	
	set {name:Nm, name extension:Ex} to oneItem
	set filename to text 1 thru ((get offset of "-" in current_name) - 2) of current_name
	if Ex is missing value then set Ex to ""
	if Ex is not "" then set Ex to "." & Ex
	set {TID, text item delimiters} to {text item delimiters, space}
	tell filename to set {theName, theDate} to {(text items 1 thru -2) as text, text item -1}
	set text item delimiters to "-"
	set {mn, dy, yr} to text items of theDate
	set text item delimiters to TID
	if (count yr) = 2 then set yr to "20" & yr
	tell application id "com.devon-technologies.thinkpro2" to set name of oneItem to theName & space & yr & my pad(mn) & my pad(dy) & Ex
	
end repeat


on pad(t)
	return text -2 thru -1 of ("0" & t)
end pad

With events and replies:

tell application "DEVONthink Pro"
	get selection
		--> {content id 99975 of database id 3}
end tell
tell application "System Events"
	keystroke "i" using {command down, shift down}
	keystroke "c" using {command down}
end tell
tell application "TextEdit"
	activate
end tell
tell application "System Events"
	keystroke "n" using {command down}
end tell
tell application "AppleScript Editor"
	the clipboard as record
		--> {Unicode text:"set {name:Nm, name extension:Ex} to oneItem
	set filename to text 1 thru ((get offset of \"-\" in current_name) - 2) of current_name
	if Ex is missing value then set Ex to \"\"
	if Ex is not \"\" then set Ex to \".\" & Ex
	set {TID, text item delimiters} to {text item delimiters, space}
	tell filename to set {theName, theDate} to {(text items 1 thru -2) as text, text item -1}
	set text item delimiters to \"-\"
	set {mn, dy, yr} to text items of theDate
	set text item delimiters to TID
	if (count yr) = 2 then set yr to \"20\" & yr
	tell application id \"com.devon-technologies.thinkpro2\" to set name of oneItem to theName & space & yr & my pad(mn) & my pad(dy) & Ex
end repeat

on pad(t)
	return text -2 thru -1 of (\"0\" & t)
end pad", string:"set {name:Nm, name extension:Ex} to oneItem
	set filename to text 1 thru ((get offset of \"-\" in current_name) - 2) of current_name
	if Ex is missing value then set Ex to \"\"
	if Ex is not \"\" then set Ex to \".\" & Ex
	set {TID, text item delimiters} to {text item delimiters, space}
	tell filename to set {theName, theDate} to {(text items 1 thru -2) as text, text item -1}
	set text item delimiters to \"-\"
	set {mn, dy, yr} to text items of theDate
	set text item delimiters to TID
	if (count yr) = 2 then set yr to \"20\" & yr
	tell application id \"com.devon-technologies.thinkpro2\" to set name of oneItem to theName & space & yr & my pad(mn) & my pad(dy) & Ex
end repeat

on pad(t)
	return text -2 thru -1 of (\"0\" & t)
end pad", scrap styles:«data styl01000000000010000E00030000000C00000000000000», «class utf8»:"set {name:Nm, name extension:Ex} to oneItem
	set filename to text 1 thru ((get offset of \"-\" in current_name) - 2) of current_name
	if Ex is missing value then set Ex to \"\"
	if Ex is not \"\" then set Ex to \".\" & Ex
	set {TID, text item delimiters} to {text item delimiters, space}
	tell filename to set {theName, theDate} to {(text items 1 thru -2) as text, text item -1}
	set text item delimiters to \"-\"
	set {mn, dy, yr} to text items of theDate
	set text item delimiters to TID
	if (count yr) = 2 then set yr to \"20\" & yr
	tell application id \"com.devon-technologies.thinkpro2\" to set name of oneItem to theName & space & yr & my pad(mn) & my pad(dy) & Ex
end repeat

on pad(t)
	return text -2 thru -1 of (\"0\" & t)
end pad", «class ut16»:"set {name:Nm, name extension:Ex} to oneItem
	set filename to text 1 thru ((get offset of \"-\" in current_name) - 2) of current_name
	if Ex is missing value then set Ex to \"\"
	if Ex is not \"\" then set Ex to \".\" & Ex
	set {TID, text item delimiters} to {text item delimiters, space}
	tell filename to set {theName, theDate} to {(text items 1 thru -2) as text, text item -1}
	set text item delimiters to \"-\"
	set {mn, dy, yr} to text items of theDate
	set text item delimiters to TID
	if (count yr) = 2 then set yr to \"20\" & yr
	tell application id \"com.devon-technologies.thinkpro2\" to set name of oneItem to theName & space & yr & my pad(mn) & my pad(dy) & Ex
end repeat

on pad(t)
	return text -2 thru -1 of (\"0\" & t)
end pad"}
	set the clipboard to "set {name:Nm, name extension:Ex} to oneItem
	set filename to text 1 thru ((get offset of \"-\" in current_name) - 2) of current_name
	if Ex is missing value then set Ex to \"\"
	if Ex is not \"\" then set Ex to \".\" & Ex
	set {TID, text item delimiters} to {text item delimiters, space}
	tell filename to set {theName, theDate} to {(text items 1 thru -2) as text, text item -1}
	set text item delimiters to \"-\"
	set {mn, dy, yr} to text items of theDate
	set text item delimiters to TID
	if (count yr) = 2 then set yr to \"20\" & yr
	tell application id \"com.devon-technologies.thinkpro2\" to set name of oneItem to theName & space & yr & my pad(mn) & my pad(dy) & Ex
end repeat

on pad(t)
	return text -2 thru -1 of (\"0\" & t)
end pad"
end tell
tell application "System Events"
	keystroke "v" using {command down}
end tell
tell application "DEVONthink Pro"
	get name of content id 99975 of database id 3
		--> "State Farm Cancellation 10-26-2006"
	get name extension of content id 99975 of database id 3
		--> error number -1728 from name extension of content id 99975 of database id 3
Result:
error "DEVONthink Pro got an error: Can't get name extension of content id 99975 of database id 3." number -1728 from name extension of content id 99975 of database id 3

Approach 2: I got the following language after much wasted effort:

tell application "DEVONthink Pro" to set theSelection to (get selection)
repeat with oneItem in theSelection
	tell application "DEVONthink Pro"
		get filename of (selection as reference)
	end tell
	
	set filename to text 1 thru ((get offset of "." in Nm) - 1) of Nm
	if Ex is missing value then set Ex to ""
	if Ex is not "" then set Ex to "." & Ex
	set {TID, text item delimiters} to {text item delimiters, space}
	tell filename to set {theName, theDate} to {(text items 1 thru -2) as text, text item -1}
	set text item delimiters to "-"
	set {mn, dy, yr} to text items of theDate
	set text item delimiters to TID
	if (count yr) = 2 then set yr to "20" & yr
	tell application "Finder" to set name of contents of oneItem to theName & space & yr & my pad(mn) & my pad(dy) & Ex
end repeat

on pad(t)
	return text -2 thru -1 of ("0" & t)
end pad
tell application "DEVONthink Pro"
	get filename of (selection as reference)
end tell

Which gives me the events and replies:

tell application "DEVONthink Pro"
	get selection
		--> {content id 99975 of database id 3}
	get selection
		--> {content id 99975 of database id 3}
	get filename of content id 99975 of database id 3
		--> "State Farm Cancellation 10-26-2006.pdf"
Result:
error "The variable Nm is not defined." number -2753 from "Nm"

If I change “Nm” to “reference”, and change “-1” to “+ 6”:

tell application "DEVONthink Pro" to set theSelection to (get selection)
repeat with oneItem in theSelection
	tell application "DEVONthink Pro"
		get filename of (selection as reference)
	end tell
	
	set filename to text 1 thru ((get offset of "." in reference) + 6) of reference
	if Ex is missing value then set Ex to ""
	if Ex is not "" then set Ex to "." & Ex
	set {TID, text item delimiters} to {text item delimiters, space}
	tell filename to set {theName, theDate} to {(text items 1 thru -2) as text, text item -1}
	set text item delimiters to "-"
	set {mn, dy, yr} to text items of theDate
	set text item delimiters to TID
	if (count yr) = 2 then set yr to "20" & yr
	tell application "Finder" to set name of contents of oneItem to theName & space & yr & my pad(mn) & my pad(dy) & Ex
end repeat

on pad(t)
	return text -2 thru -1 of ("0" & t)
end pad
tell application "DEVONthink Pro"
	get filename of (selection as reference)
end tell

With the following events and replies:

tell application "DEVONthink Pro"
	get selection
		--> {content id 99975 of database id 3}
	get selection
		--> {content id 99975 of database id 3}
	get filename of content id 99975 of database id 3
		--> "State Farm Cancellation 10-26-2006.pdf"
end tell
tell current application
	offset of "." in reference
		--> 0
Result:
error "Can't get text 1 thru 6 of reference." number -1728 from text 1 thru 6 of reference

I don’t know if there is something obvious I am missing (quite likely!), even though I am trying to do this within DT.

Cheers!

Of course it doesn’t work, because the loop index variable oneItem must be an alias
and I suspect that selection of Devonthink is not a list of aliases
Read the dictionary of Devonthink to find out the class of an item of selection. Maybe it could be coerced to alias.

Thanks for the reply. Please forgive the silly mistakes I make-I am quite new to this!

Here is an example of a script from DT that replaces text in a title. I don’t know if it helps with the internal language used by DT:

tell application id "com.devon-technologies.thinkpro2"
	try
		set this_selection to the selection
		if this_selection is {} then error "Please select some contents."
		
		repeat
			set search_string to display name editor "Replace Text" info "Enter text to find:"
			if search_string is not "" then exit repeat
		end repeat
		
		set replacement_string to display name editor "Replace Text" info "Enter replacement text:"
		
		set od to AppleScript's text item delimiters
		repeat with this_item in this_selection
			set current_name to name of this_item
			if current_name contains search_string then
				set AppleScript's text item delimiters to search_string
				set text_item_list to every text item of current_name
				set AppleScript's text item delimiters to replacement_string
				set new_item_name to text_item_list as string
				set the name of this_item to new_item_name
			end if
		end repeat
		set AppleScript's text item delimiters to od
		
	on error error_message number error_number
		if the error_number is not -128 then display alert "DEVONthink Pro" message error_message as warning
	end try
end tell

Is this helpful at all in terms of the alias?

Thanks!

It doesn’t help very much. An element of DT seems to be like a Finder file specifier.
I see there is a name property but the script requires also a name extension property

Assuming there is no name extension property this is a blind attempt to
extract the name extension right from the file name


tell application "DEVONthink Pro" to set theSelection to (get selection)
repeat with oneItem in theSelection
	set filename to name of oneItem
	if filename contains "." then
		set {TID, text item delimiters} to {text item delimiters, "."}
		tell filename to set {Nm, Ex} to {(text items 1 thru -2) as text, "." & text item -1}
		set text item delimiters to TID
	else
		set Ex to ""
		set Nm to filename
	end if
	set {TID, text item delimiters} to {text item delimiters, space}
	tell Nm to set {theName, theDate} to {(text items 1 thru -2) as text, text item -1}
	set text item delimiters to "-"
	set {dy, mn, yr} to text items of theDate
	set text item delimiters to TID
	if (count yr) = 2 then set yr to "20" & yr
	tell application "DEVONthink Pro" to set name of oneItem to theName & space & yr & my pad(mn) & my pad(dy) & Ex
end repeat

on pad(t)
	return text -2 thru -1 of ("0" & t)
end pad

I know the word "genius’ gets bandied about a lot, but you, sir, are a genius!
:smiley:

It works perfectly.

After your post, I reviewed all the settings/prefs in the program, and found that I had imported all my data without extensions. Your hunch was correct, and your new script addresses it perfectly.

Kudos and thanks, Stefan! You have improved my day considerably.