Add sequential numbering to Folder depending on variable

how-to
finder

(DRicho) #1

Hi,

I need a little help with a script I’m working on.
I have a script that basically creates a folder with the current date.month.year with a prefix of 00 |
So final folder looks like this 00 | 07.03.2019, depending on the date.

I was hoping to add to the script so that it looks in the location and if folders within are say:
01 | 05.03.2019
02 | 06.03.2019
03 | 07.03.2019

Instead of adding a folder of just 00 | 08.03.2019
It looks and the prefix of the exisiting folders and then sequentially numbers the folder to 04 | 08.03.2019

This is my script so far:

tell application "Finder"
	try
		if exists Finder window 1 then
			set thisPath to (the target of the front window) as alias
		else
			set thisPath to (path to desktop)
		end if
	on error
		return
	end try
end tell

set x to my the_perfect_datestring()
if x is not "-ERROR" then
	set fullPath to thisPath & x as text
	tell application "Finder"
		try
			--activate
			if not (exists fullPath) then
				set y to make new folder at thisPath with properties {name:x}
			end if
			activate
			open y
		end try
	end tell
end if
on the_perfect_datestring()
	try
		
		set cd to (the current date)
		set the_year to year of (cd) as number
		set the_month to month of (cd) as number
		set the_day to day of (cd) as number
		if the_month < 10 then set the_month to "0" & the_month
		if the_day < 10 then set the_day to "0" & the_day
		return (("00 | " & the_day & "." & the_month & "." & the_year) as string)
	on error
		return "-ERROR"
	end try
end the_perfect_datestring

(Ed Stockly) #2

Just to be clear, if there is not a “00 | 08.03.2019” should it look for a " 01.03.2019"?

Here’s a quick and dirty version. It’s very inefficient because it repeats the part where it gets the date segments for the folder name. That could be streamlined.

tell application "Finder"
   try
      if exists Finder window 1 then
         set thisPath to (the target of the front window) as alias
      else
         set thisPath to (path to desktop)
      end if
   on error
      return
   end try
end tell

set x to my the_perfect_datestring(0)
if x is not "-ERROR" then
   set fullPath to thisPath & x as text
   
   try
      --activate
      tell application "Finder"
         repeat
            if not (exists fullPath) then
               set y to make new folder at thisPath with properties {name:x}
               exit repeat
            else
               set prefix to word 1 of x as number
               set prefix to prefix + 1
               set x to my the_perfect_datestring(prefix)
               set fullPath to thisPath & x as text
            end if
         end repeat
         activate
         open y
      end tell
   end try
end if

on the_perfect_datestring(prefix)
   try
      
      set cd to (the current date)
      set the_year to year of (cd) as number
      set the_month to month of (cd) as number
      set the_day to day of (cd) as number
      if the_month < 10 then set the_month to "0" & the_month
      if the_day < 10 then set the_day to "0" & the_day
      if prefix < 10 then set prefix to "0" & prefix as text
      return ((prefix & " | " & the_day & "." & the_month & "." & the_year) as string)
   on error
      return "-ERROR"
   end try
end the_perfect_datestring

(Ed Stockly) #3

Here’s a slightly better version…

tell application "Finder"
   try
      if exists Finder window 1 then
         set thisPath to (the target of the front window) as alias
      else
         set thisPath to (path to desktop)
      end if
   on error
      return
   end try
end tell

set folderRoot to my the_perfect_datestring()
if folderRoot is not "-ERROR" then
   set folderName to "00" & folderRoot as text
   set fullPath to thisPath & folderName as text
   
   set prefix to 0
   tell application "Finder"
      repeat
         if not (exists fullPath) then
            set newFolder to make new folder at thisPath with properties {name:folderName}
            exit repeat
         else
            set prefix to prefix + 1
            if prefix < 10 then set prefix to "0" & prefix as text
            set folderName to prefix & folderRoot
            set fullPath to thisPath & folderName as text
         end if
      end repeat
      activate
      open newFolder
   end tell
end if

on the_perfect_datestring()
   try
      set cd to (the current date)
      set the_year to year of (cd) as number
      set the_month to month of (cd) as number
      set the_day to day of (cd) as number
      if the_month < 10 then set the_month to "0" & the_month
      if the_day < 10 then set the_day to "0" & the_day
      return ((" | " & the_day & "." & the_month & "." & the_year) as string)
   on error
      return "-ERROR"
   end try
end the_perfect_datestring


(DRicho) #4

This is exactly what I’m after. Thank you estockly!


(Nigel Garvey) #5

Hi both.

As it stands, the script errors when prefix gets up to 10 because folderName then gets set to a list. (Integer & text --> {integer, text}.) Also, once the folder gets quite full and you have to do several tests before finding a vacant name, it may be faster to check candidate names against a list of existing names instead of having the Finder individually check for the existence of each item on disk. (Edit: Although come to think of it, it depends on how many folders there are per date. Do the numbers reset to zero for each date, or do they have to follow through in sequence regardless? If there’s only one folder per date, it would be easier to leave out the prefix and format the date in year.month.day order instead.)


(Ed Stockly) #6

Nice catch, Nigel, I must have stopped before I got to 10 folders!

Here’s a new version with Nigel’s comments taken into account.

(Also, in this version I noted out the Open command, so I can just run it and run it without having to bring the containing folder to the front each time. When done experimenting with it, unnote that line

tell application "Finder"
   try
      if exists Finder window 1 then
         set thisPath to (the target of the front window) as alias
      else
         set thisPath to (path to desktop)
      end if
   on error
      return
   end try
end tell

set folderRoot to my the_perfect_datestring()
if folderRoot is not "-ERROR" then
   set folderName to "00" & folderRoot as text
   set fullPath to thisPath & folderName as text
   set prefix to 0
   tell application "Finder"
      set listOfFolderNames to the name of every folder of thisPath
      repeat
         if folderName is not in listOfFolderNames then
            --if not (exists fullPath) then
            set newFolder to make new folder at thisPath with properties {name:folderName}
            exit repeat
         else
            set prefix to prefix + 1
            if prefix < 10 then set prefix to "0" & prefix as text
            set folderName to (prefix as text) & folderRoot
            set fullPath to thisPath & folderName as text
         end if
      end repeat
      activate
      --open newFolder
   end tell
end if

on the_perfect_datestring()
   try
      set cd to (the current date)
      set the_year to year of (cd) as number
      set the_month to month of (cd) as number
      set the_day to day of (cd) as number
      if the_month < 10 then set the_month to "0" & the_month
      if the_day < 10 then set the_day to "0" & the_day
      return ((" | " & the_day & "." & the_month & "." & the_year) as string)
   on error
      return "-ERROR"
   end try
end the_perfect_datestring


(Ed Stockly) #7

Also, if this were my script I’d do things a little differently. Particularly I wouldn’t use “.” in the names. I’d prefer “-”


(Nigel Garvey) #8

DRicho hasn’t answered my question about what to do when the date changes, but here’s a version in which the prefices don’t go back to “00”:

try
	tell application "Finder" to set thisPath to (the target of the front Finder window) as alias
on error
	set thisPath to (path to desktop)
end try

set folderRoot to my the_perfect_datestring()

set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to linefeed
tell application "Finder" to set existingNames to linefeed & name of every item of thisPath
set AppleScript's text item delimiters to astid

set prefix to 0
repeat
	if (prefix < 10) then
		set namePrefix to "0" & prefix & " | "
	else
		set namePrefix to (prefix as text) & " | "
	end if
	
	if (existingNames contains (linefeed & namePrefix)) then
		set prefix to prefix + 1
	else
		tell application "Finder" to set newFolder to (make new folder at thisPath with properties {name:namePrefix & folderRoot})
		exit repeat
	end if
end repeat

tell application "Finder"
	activate
	open newFolder
end tell

on the_perfect_datestring()
	set {year:the_year, month:the_month, day:the_day} to (current date)
	tell (the_year * 10000 + the_month * 100 + the_day as text) to return text 7 thru 8 & "." & text 5 thru 6 & "." & text 1 thru 4
end the_perfect_datestring

(DRicho) #9

Hi Nigel,

Sorry for the late reply, I have been away. Thank you for your script. I’m very much a beginner when it comes to scripting. I usually borrow peoples scrips and adjust accordingly so they probably are not the best.
Your script works great!
Just a quick one: if the Year was to display as 19 and not 2019 how would I go about this?
Thanks again.

D


(Nigel Garvey) #10

Hi D.

At the end of the penultimate line of the script, change text 1 thru 4 to text 3 thru 4. So the full handler would be:

on the_perfect_datestring()
	set {year:the_year, month:the_month, day:the_day} to (current date)
	tell (the_year * 10000 + the_month * 100 + the_day as text) to return text 7 thru 8 & "." & text 5 thru 6 & "." & text 3 thru 4
end the_perfect_datestring

The tell line calculates an eight-digit number from the date properties (so today would be 20190313), coerces it to text, and picks out the digit substrings in the required order. Any leading zeros occur naturally in the eight-digit number. AppleScript month constants are coerced to integer (or are treated as such) automatically when mathematical operations are applied to them:

March * 100 --> 300

(DRicho) #11

Thanks Nigel! I should have been able to figure that out, but you explain it very well.