Finder doesn't recognise renamed folder

This script has stopped working since updating to High Sierra (& presumably Mojave).

I use it to back up a website (though it works for any folder!): select the folder & it makes a time-stamped copy to the back up location.

It’s failing because Finder no longer finds the copy it makes once it renames it, so can’t move it. Any ideas how to fix?? Thanks.


--"Backup Site"
---------------------

(* ==== PROPERTIES ==== *)

global saveFolder
global saveFolderLocation
global myFolder
global theDuplicateAlias

property saveFolderName : "BACKUP" --!!


(* ==== HANDLERS ==== *)

--VERIFY FOLDER
on verifyFolder()
	tell application "Finder"
		try
			--check backup folder
			if not (exists folder saveFolderName of folder saveFolderLocation) then
				make folder at folder saveFolderLocation with properties {name:saveFolderName}
			end if
		on error the error_message number the error_number
			beep
			display dialog "Error: " & the error_number & ". " & the error_message buttons {"Cancel"} default button 1 with icon 0
		end try
	end tell
end verifyFolder


--TIME STAMP DUPLICATE
--NB: for both files & folders
on timestampedduplicate(theItem)
	tell application "Finder"
		set folderCheck to theItem
		if folder (folderCheck as text) exists then
		else
			set extensionhidden to extension hidden of theItem
			set extension hidden of theItem to true
		end if
		set theItemName to displayed name of theItem
		if folder (folderCheck as text) exists then
		else
			set theItemExtension to name extension of theItem
		end if
		set upOneLevelFolder to folder of theItem as alias
		set {year:y, month:m, day:d, time string:t} to (current date)
		set date_format to (y * 10000 + m * 100 + d) as string
		set time_format to (t) as string
		set t to (do shell script "echo " & "'" & t & "'" & " | sed  's/://g' ")
		set thedate to date_format & " " & t as text
		if folder (folderCheck as text) exists then
			set theNewName to theItemName & " " & thedate as text
		else
			set theNewName to theItemName & " " & thedate & "." & theItemExtension as text
		end if
		log theNewName
		set theDuplicate to duplicate theItem to upOneLevelFolder replacing no
		set theDuplicateAlias to theDuplicate as alias
		set name of theDuplicateAlias to theNewName
		if folder (folderCheck as text) exists then
		else
			if extensionhidden then
				set extension hidden of theDuplicateAlias to true
				set extension hidden of theItem to true
			else
				set extension hidden of theDuplicateAlias to false
				set extension hidden of theItem to false
			end if
		end if
	end tell
end timestampedduplicate


(* ==== SCRIPT ==== *)

--initialise
set path2home to (path to home folder) as text
set saveFolderLocation to path2home & "Library:Application Support:"
set saveFolder to saveFolderLocation & saveFolderName & ":"
set defaultLocation to path2home & "Sites:"
my verifyFolder()

--dialog
display dialog "Backup site?" buttons {"Cancel", "View Backups", "Choose Site"} default button 3 with icon 1
set button_returned to button returned of the result

--view
if button_returned is "View Backups" then
	tell application "Finder"
		open folder saveFolder
	end tell
	
	--dialog
	activate me
	display dialog "Backup folder opened..." buttons {"Backup Site", "Done"} default button 2 with icon 1
	set button_returned to button returned of the result
	
end if

--backup
if button_returned is in {"Choose Site", "Backup Site"} then
	
	tell application "Finder"
		set myFolder to choose folder default location defaultLocation as alias --choose site
	end tell
	
	my timestampedduplicate(myFolder) --make duplicate
	
	tell application "Finder"
		move folder theDuplicateAlias to folder saveFolder --move to backup folder
		(*FAILING HERE!!*)
	end tell
	
	--dialog
	activate me
	display dialog "Site backed up." buttons {"Done"} default button 1 with icon 1
	
end if


(* ==== END ==== *)

I can’t test because I don’t use networks.
I just guess that the site is not aware of the new name when the Finder try to move the renamed folder.
For my own use I would not trigger Finder but would rely upon ASObjC which is more efficient but just to play I edited your script in a way which, I guess, would work.
It no longer use a renamed temporary folder but duplicate directly into the BACKUP folder then rename the replicate.
I changed also the structure so that there is no “living” global values which are stored on disk.


--"Backup Site"
---------------------

my germaine()

(* ==== HANDLERS ==== *)

--VERIFY FOLDER
on verifyFolder(saveFolderName, saveFolderLocation)
	tell application "Finder"
		try
			--check backup folder
			if not (exists folder saveFolderName of folder saveFolderLocation) then
				make folder at folder saveFolderLocation with properties {name:saveFolderName}
			end if
		on error the error_message number the error_number
			beep
			display dialog "Error: " & the error_number & ". " & the error_message buttons {"Cancel"} default button 1 with icon 0
		end try
	end tell
end verifyFolder


on germaine()
	--initialise
	set saveFolderName to "BACKUP"
	set path2home to (path to home folder) as text
	set saveFolderLocation to path2home & "Library:Application Support:"
	set saveFolder to saveFolderLocation & saveFolderName & ":"
	set defaultLocation to path2home & "Sites:"
	my verifyFolder(saveFolderName, saveFolderLocation)
	
	--dialog
	display dialog "Backup site?" buttons {"Cancel", "View Backups", "Choose Site"} default button 3 with icon 1
	set button_returned to button returned of the result
	
	--view
	if button_returned is "View Backups" then
		tell application "Finder"
			open folder saveFolder
		end tell
		
		--dialog
		activate me
		display dialog "Backup folder opened..." buttons {"Backup Site", "Done"} default button 2 with icon 1
		set button_returned to button returned of the result
		
	end if
	
	--backup
	if button_returned is in {"Choose Site", "Backup Site"} then
		
		tell application "Finder"
			set myFolder to choose folder default location defaultLocation as alias --choose site
			
			set replicate to duplicate myFolder to folder saveFolder
		end tell
		
		# As we want to rename a folder, no need to play with extension hidden
		set {year:y, month:m, day:d, hours:h, minutes:mm, seconds:s} to (current date)
		set date_format to (y * 10000 + m * 100 + d) as string
		set time_format to (h * 10000 + mm * 100 + s) as string
		set thedate to date_format & " " & time_format
		
		tell application "Finder"
			set newName to (name of myFolder) & " " & thedate
			set name of replicate to newName
		end tell
		
		--dialog
		activate me
		display dialog "Site backed up." buttons {"Done"} default button 1 with icon 1
		
		
	end if
end germaine

(* ==== END ==== *)

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) lundi 11 février 2019 14:49:36

I’m seeing a bug in Mojave whereby theDuplicateAlias isn’t tracking the name change here. It seems workroundable:

set theNewName to "BACKUP"

tell application "Finder"
	
	set upOneLevelFolder to container of theItem as alias -- 'folder of theItem' is incorrect.
	
	
	set theDuplicate to duplicate theItem -- to upOneLevelFolder replacing no
	set name of theDuplicate to theNewName -- Change the name before setting the alias.
	set theDuplicateAlias to (item theNewName of upOneLevelFolder) as alias
	
end tell

But Yvan’s script looks as if it may be better.

@Yvan Thanks! That works.

@Nigel The workaround solves issue too :slight_smile: Good to know for other scripts

Here is a version using ASObjC.

use AppleScript version "2.5"

use framework "Foundation"
use scripting additions

my germaine()

#=====#=====#=====#=====#=====#=====
# Some handlers borrowed to Shane STANLEY

-- Creates a new folder. There is no error if the folder already exists, and it will also create intermediate folders if required
on createFolderNamed:proposedName inFolder:POSIXPath
	local |⌘|, theFolderURL, theDestURL, theFileManager
	
	set |⌘| to current application
	set theFolderURL to |⌘|'s |NSURL|'s fileURLWithPath:POSIXPath
	if class of proposedName is text then set proposedName to |⌘|'s NSString's stringWithString:proposedName
	set proposedName to proposedName's stringByReplacingOccurrencesOfString:"/" withString:":"
	set theDestURL to theFolderURL's URLByAppendingPathComponent:proposedName
	set theFileManager to |⌘|'s NSFileManager's |defaultManager|()
	-- set {theResult, theError} to theFileManager's createDirectoryAtURL:theDestURL withIntermediateDirectories:true attributes:(missing value) |error|:(reference)
	theFileManager's createDirectoryAtURL:theDestURL withIntermediateDirectories:true attributes:(missing value) |error|:(missing value)
	-- if not (theResult as boolean) then error (theError's |localizedDescription|() as text)
	
	return theDestURL's |path| as text
end createFolderNamed:inFolder:

#=====#=====#=====#=====#=====#=====

on copyThis:POSIXPath intoFolder:folderOrPath addingString:theStamp
	local |⌘|, theSourceURL, destName, theFolderURL, theDestURL
	
	set |⌘| to current application
	set theSourceURL to |⌘|'s |NSURL|'s fileURLWithPath:POSIXPath
	set destName to theSourceURL's |lastPathComponent|()
	set destName to destName's stringByAppendingString:(space & theStamp)
	set theFolderURL to |⌘|'s |NSURL|'s fileURLWithPath:folderOrPath
	set theDestURL to theFolderURL's URLByAppendingPathComponent:destName
	my copyFromURL:theSourceURL toURL:theDestURL withReplacing:true
	
end copyThis:intoFolder:addingString:

#=====

-- This handler is called by other handlers, and is not meant to called directly
on copyFromURL:sourceURL toURL:destinationURL withReplacing:replaceFlag
	set |⌘| to current application
	set theFileManager to |⌘|'s NSFileManager's |defaultManager|()
	set {theResult, theError} to (theFileManager's copyItemAtURL:sourceURL toURL:destinationURL |error|:(reference))
	if not theResult as boolean then
		if replaceFlag and (theError's code() as integer = |⌘|'s NSFileWriteFileExistsError as integer) then -- it already exists, so try replacing
			-- create suitable temporary directory in destinationURL's parent folder
			set {tempFolderURL, theError} to theFileManager's URLForDirectory:(|⌘|'s NSItemReplacementDirectory) inDomain:(|⌘|'s NSUserDomainMask) appropriateForURL:(destinationURL's |URLByDeletingLastPathComponent|()) create:true |error|:(reference)
			if tempFolderURL = missing value then error (theError's |localizedDescription|() as text) -- failed, so return error
			-- copy sourceURL to temp directory
			set tempDestURL to tempFolderURL's URLByAppendingPathComponent:(destinationURL's |lastPathComponent|())
			set {theResult, theError} to theFileManager's copyItemAtURL:sourceURL toURL:tempDestURL |error|:(reference)
			if not theResult as boolean then
				-- copy failed, so delete temporary directory and return error
				theFileManager's removeItemAtURL:tempFolderURL |error|:(missing value)
				error (theError's |localizedDescription|() as text)
			end if
			-- replace existing file with temp file atomically, then delete temp directory
			set {theResult, theError} to theFileManager's replaceItemAtURL:destinationURL withItemAtURL:tempDestURL backupItemName:(missing value) options:(|⌘|'s NSFileManagerItemReplacementUsingNewMetadataOnly) resultingItemURL:(missing value) |error|:(reference)
			theFileManager's removeItemAtURL:tempFolderURL |error|:(missing value)
			-- if replacement failed, return error
			if not theResult as boolean then error (theError's |localizedDescription|() as text)
		else -- replaceFlag is false or an error other than file already exists, so return error
			error (theError's |localizedDescription|() as text)
		end if
	end if
end copyFromURL:toURL:withReplacing:

#=====#=====#=====#=====#=====#=====

on formatDate:theDate usingFormat:formatString
	set theFormatter to current application's NSDateFormatter's new()
	theFormatter's setDateFormat:formatString
	set theString to theFormatter's stringFromDate:theDate
	return theString as text
end formatDate:usingFormat:

#=====#=====#=====#=====#=====#=====

on germaine()
	--initialise
	set saveFolderName to "BACKUP"
	set path2home to (path to home folder) as text
	set saveFolderLocation to path2home & "Library:Application Support:"
	set defaultLocation to path2home & "Sites:"
	
	set POSIXSaveFolder to my createFolderNamed:saveFolderName inFolder:(POSIX path of saveFolderLocation)
	
	--dialog
	display dialog "Backup site?" buttons {"Cancel", "View Backups", "Choose Site"} default button 3 with icon 1
	set button_returned to button returned of the result
	
	--view
	if button_returned is "View Backups" then
		tell application "Finder"
			open folder (POSIX file POSIXSaveFolder)
		end tell
		
		--dialog
		activate me
		display dialog "Backup folder opened..." buttons {"Backup Site", "Done"} default button 2 with icon 1
		set button_returned to button returned of the result
		
	end if
	
	--backup
	if button_returned is in {"Choose Site", "Backup Site"} then
		
		set myFolder to choose folder default location defaultLocation as alias --choose site
		
		# As we want to rename a folder, no need to play with extension hidden
		set theStamp to my formatDate:(current date) usingFormat:"yyyyMMdd HHmmss"
		
		# Copy myFolder into saveFolder adding theStamp to the final name
		my copyThis:(POSIX path of myFolder) intoFolder:POSIXSaveFolder addingString:theStamp
		
		--dialog
		activate me
		display dialog "Site backed up." buttons {"Done"} default button 1 with icon 1
		
		
	end if
end germaine

(* ==== END ==== *)

This one creates the replicate directly with the stamped name.

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) mardi 12 février 2019 12:13:46