Creating a Duplicate Folder Structure and Moving Files by Filename

I’m new to AppleScript (and scripting in genera). I searched the forum and tried what I could, but now I’m stumped and would love some help.

I’m recording video on my Mac using a program that stores video in one type of file format, then I need to use Compressor to convert it to another format and store it in a separate folder, but with the same directory structure. Here is what I’ve done so far:

  1. Attach a Folder Action Script to the main video storage folder that attaches a DIFFERENT script automatically to any folder created under that folder. I call this one “add script to subfolder.scpt”. It works perfectly, and here it is:

property ScriptName : "SendVideoToDroplet.scpt"
property ScriptPath : ":Library:Scripts:Folder Action Scripts:" & ScriptName

on adding folder items to thisfolder after receiving theseitems
	tell application "Finder"
		repeat with thisItem in theseitems
			if (class of item thisItem is folder) then
				tell application "System Events"
					attach action to thisItem as alias using ScriptPath
				end tell
			end if
		end repeat
	end tell
end adding folder items to

  1. I have created a “Droplet.app” file in Compressor that will do the exact video conversion I need, in the background. I’ve also created an applescript, referenced in the prior script, that sends any new items in that folder, to the Droplet. The Droplet can only output files to a single, specified folder. However, I can add anything I want to the output filename, such as “-converted”. This script is as follows:

on adding folder items to thisFolder after receiving theItems	
	-- this is the standard intro for a folder action	
	repeat with f in theItems		
		-- wait for the item to be all there		
		set Was to 0		
		set isNow to 1		
		repeat while isNow ≠ Was		
			-- the basic idea is that the script loops until the file size is the same for more than 30 seconds. That means the file has finished copying.			
			set Was to size of (info for f)			
			-- this section is getting the file size of the video			
			delay 30			
			set isNow to size of (info for f)			
			-- this section is sampling the file size 30 seconds later			
		end repeat		
		tell application "Finder"			
			open theItems using application file "Droplet.app" of folder "Desktop" of folder "division" of folder "Users" of startup disk			
		end tell		
	end repeat -- get next item f in thisFolder	
end adding folder items to

  1. Here’s where I need help… I want to move the output files from the droplet, to a similar but separate directory structure. For example, right now the original movies are in: Playback Storage:QTAKE Projects:Day 1: - I want the output files from Compressor to be in: Playback Storage:Converted Projects: Day 1: - where the folder “Day 1” would be created by a Folder Action Script to match the directory structure of the original file.

My thought is to set the compressor droplet to create an output file called “OriginalFileName-converted.mp4” - where we added “-converted”. Then, add to the “SendVideoToDroplet.scpt” Folder Action Script, some script where “if the filename contains -converted, then create a folder with the same name/structure as this one, but under the Converted Projects folder, and move the file there. Otherwise, continue the script - which sends the file to the Droplet”.

However, whatever I try seems to fail at that part. I would really appreciate any help that could be given to me.

Thanks in advance…

Model: Mac Pro - 12 Core, 24gb RAM
AppleScript: Latest
Browser: Safari 533.21.1
Operating System: Mac OS X (10.7)

Hi, division. Welcome to MacScripter.

I’m sorry to see you haven’t had a reply yet.

Three things about your first script:

  1. The path “:Library:Scripts:Folder Action Scripts:” & ScriptName refers to a file in the local Scripts hierarchy. It’s more usual to put Folder Action scripts in the user’s hierarchy, ie. “:Users::Library:Scripts:Folder Action Scripts:” & ScriptName
  2. It’s not a good idea to put a ‘tell’ statement for one application inside that for another. It can lead to slow-downs and/or terminology conflicts.
  3. A surprise for me, this one: although it still currently compiles and works, ‘attach action to’ is no longer listed in System Events’s dictionary and appears to have been superceded by another process ” one that’s quite common in other contexts. For this, you only have to give the script’s name, as it’s assumed to be in the user’s “Folder Action Scripts” folder.

property ScriptName : "SendVideoToDroplet.scpt"

on adding folder items to thisfolder after receiving theseitems
	tell application "System Events"
		repeat with thisItem in theseitems
			if (thisItem's kind is "Folder") then
				set thisAction to (make new folder action at end of folder actions with properties {path:(thisItem as text)})
				make new script at end of thisAction's scripts with properties {name:ScriptName}
			end if
		end repeat
	end tell
end adding folder items to

If I’ve understood your query, the “Day 1” folder is one to which the action has been attached above. A good time to create the equivalent “Day 1” in “Converted Projects” would be while dealing with the attachment to the original. If “Converted Projects” already exists and “Day 1” (or whatever) is definitely an immediate subfolder of “QTAKE Projects”, the new folder can be created with the addition of a single line:


property ScriptName : "SendVideoToDroplet.scpt"

on adding folder items to thisfolder after receiving theseitems
	tell application "System Events"
		repeat with thisItem in theseitems
			if (thisItem's kind is "Folder") then
				set thisAction to (make new folder action at end of folder actions with properties {path:(thisItem as text)})
				make new script at end of thisAction's scripts with properties {name:ScriptName}
				-- Make an equivalent folder in the "Converted Projects" folder.
				make new folder at end of folders of folder "Converted Projects" of thisItem's container's container with properties {name:(get thisItem's name)}
			end if
		end repeat
	end tell
end adding folder items to

Alternatively, the following variation works wherever in the “QTAKE Projects” hierarchy “Day 1” may be and even if “Converted Projects” itself hasn’t been created yet:


property ScriptName : "SendVideoToDroplet.scpt"

on adding folder items to thisfolder after receiving theseitems
	tell application "System Events"
		repeat with thisItem in theseitems
			if (thisItem's kind is "Folder") then
				set thisAction to (make new folder action at end of folder actions with properties {path:(thisItem as text)})
				make new script at end of thisAction's scripts with properties {name:ScriptName}
				-- Make an equivalent folder in the "Converted Projects" hierarchy.
				my makeEquivalentFolder(thisItem)
			end if
		end repeat
	end tell
end adding folder items to

on makeEquivalentFolder(thisItem)
	-- Get the full POSIX path of thisItem.
	set folderPath to POSIX path of thisItem
	
	-- Substitute "/Converted Projects/" for "/QTAKE Projects/" in it.
	set astid to AppleScript's text item delimiters
	set AppleScript's text item delimiters to "/QTAKE Projects/"
	set newFolderPath to folderPath's text items
	set AppleScript's text item delimiters to "/Converted Projects/"
	set newFolderPath to newFolderPath as text
	set AppleScript's text item delimiters to astid
	
	-- Create whatever doesn't already exist in the folder chain specified by the new path.
	do shell script ("mkdir -p " & quoted form of newFolderPath)
end makeEquivalentFolder

Your second script has an error in that it’s sending all the items to the droplet each time round the repeat. It should only send f. Another, lesser thing is that the ‘info for’ command is now deprecated. I’ve assumed here that none of the “files” will be bundles and have used ‘get eof’ to get the sizes.

As you’ve obviously realised, the droplet’s saving of the converted files back to the original folder retriggers the folder action, so the script has to decide whether it’s dealing with originals or conversions. It might look something like this, which I haven’t tested in context:


on adding folder items to thisFolder after receiving theItems
	-- this is the standard intro for a folder action	
	repeat with f in theItems
		-- wait for the item to be all there		
		set Was to -1
		set isNow to 0
		repeat until (isNow = Was)
			-- the basic idea is that the script loops until the file size is the same for more than 30 seconds. That means the file has finished copying.			
			set Was to isNow
			delay 30
			set isNow to (get eof f) -- this section is sampling the file size 30 seconds later			
		end repeat
		
		if ((f as text) contains "-converted.") then
			-- If this is a converted file, work out where it should go in the "Converted Projects" hierarchy and move it there. 
			set fPath to quoted form of POSIX path of f
			
			set astid to AppleScript's text item delimiters
			set AppleScript's text item delimiters to "/QTAKE Projects/"
			set newPath to fPath's text items
			set AppleScript's text item delimiters to "/Converted Projects/"
			set newPath to newPath as text
			-- Uncomment the next four lines if you want to strip "-converted" from the name too.
			(* set AppleScript's text item delimiters to "-converted."
			set newPath to newPath's text items
			set AppleScript's text item delimiters to "."
			set newPath to newPath as text *)
			set AppleScript's text item delimiters to astid
			
			do shell script ("mv " & fPath & space & newPath)
		else -- Not a converted file. Convert it.
			tell application "Finder" to open f using application file "Droplet.app" of desktop
		end if
	end repeat -- get next item f in thisFolder	
end adding folder items to

Wow - what a great, thorough reply. Thank you so much for your help. Almost there, but I still have one issue.

I tested this just now, using the last versions of the scripts you wrote as-is. The scripts accurately create the folder structure in “Converted Projects” and do pass the video file on to the Droplet.app, however, it isn’t moving the “-converted.mp4” file to the newly created folder.

I tried changing your “repeat” to:

	repeat with f in theItems
		-- wait for the item to be all there		
		set Was to -1
		set isNow to 0
		repeat until (isNow = Was)
			-- the basic idea is that the script loops until the file size is the same for more than 30 seconds. That means the file has finished copying.			
			set Was to (get eof f)
			delay 30
			set isNow to (get eof f) -- this section is sampling the file size 30 seconds later			
		end repeat

Note: line changed was “set Was to (get eof f)” from “set Was to isNow” because I thought the problem was there. I’m not quite sure where the problem is now. It just leaves that “-converted.mp4” file in the directory that Compressor puts it in.

I wonder if the problem is coming from the fact that Compressor, while converting the file, creates a file in that directory called “-converted.mp4-1” while it’s converting… That file size changes until its done, at which point it’s called “-converted.mp4”. Note that if we change the type of file it gets converted “to”, it might have a different extension, such as “-converted.mov”.

I don’t see why that’d be the problem, but I also don’t see why its not moving the file. Any thoughts?

Thanks again for your help.

Oops. I left out the phrase ‘do shell script’ in the line which does that. I’ve now corrected it in the script above. I’m glad I saw that before going to bed! :rolleyes:

It could turn out to be an issue, because renaming files in the folder is another thing which can trigger the Folder Action. Let me know how it goes.

Amazing job - thank you for your help. It works like a charm, even when I drop two files in there at the same time. The only failure point I can find, is if I delete any of the auto-created directories in the “Converted Projects” folder. When I have time I’ll look into a way to re-create them if they were deleted, in case someone deletes them on accident or on purpose, without knowing about this.

Very great. If you’d like me to leave a donation for the site, I can do so via paypal!