Help a newbie switcher with copying files..please...

Hi.

I’ve had a Macbook for two weeks now witch is my first mac…
I’m a supergeek on windows but from now on I’m on mac…

I’m currently trying to make a applescript folder action to help me sort and copy images from my cameras…

As it is now I have a script that calls a terminal command (jhead) to rename new files in the folder. That works fine, and the files get a name like “20061002-140200.jpg” (ie. year month date - hour minut second).

But I can’t figure out how to copy and move the files after they have been renamed. Want I want is to:

  1. rename the newly added files (done)
  2. copy the renamed original files to a backup folder
  3. then move the files to and second folder.

Should be simple but I just can’t get it to work…
Another question is when using folders on the mac in applescript like
MacHD:Users:martin:blablabla
should this be in english like above or can I use danish like this:
MacHD:Brugere:martin:blabla
or does applescript work with both?

Should say that I have indeed been looking on this site, googleing etc etc. to figure this out, but the information is either very badly written or mainly for mac geeks… Been trying a lot of diferrent syntaxes but to no avail…

Please help
Martin Andersen

You can’t ‘copy’ a file, only object values. You must ‘duplicate’ a file.

What’s copy for then? This illustrates (just click the link at the top of the script to copy this to your Script Editor):


set b to 6
set c to b
display dialog "After the set c to b" & return & "c = " & c & " as expected."
set c to 8
display dialog "After setting c to 8" & return & "b = " & b & return & "c = " & c & return & "b and c remain distinct."


set b to {1, 2, 3}
set c to b
set item 2 of c to 7
display dialog "With 'set =' for a list, however," & return & "b = " & makeMsg(b) & "c = " & makeMsg(c) & return & "setting c to b was parsimonious; c was just a reference to b."

set b to {1, 2, 3}
copy b to c
set item 2 of c to 7
display dialog "But with 'copy b to c'," & return & "b = " & makeMsg(b) & "c = " & makeMsg(c) & "they remain distinct. c is a different object from b."

to makeMsg(alist)
	set msg to "{"
	repeat with k from 1 to (count alist) - 1
		set msg to msg & item k of alist & ", "
	end repeat
	set msg to msg & end of alist & "}" & return
end makeMsg

Oh, yes sorry, I’ve used the wrong term, but ‘dupclicate’ is what I have tried with… Can’t get to work, tried alot of different ways I found on the net…

Martin

This does it for me. You’ll have to change each of the paths as appropriate, but I tested this with three files in “MoveFrom” and it successfully duplicated them to “Bkup” then moved them to “MoveTo”.


set sourceF to alias ((path to desktop folder as text) & "MoveFrom:")
set destF to alias ((path to desktop folder as text) & "MoveTo:")
set bkupF to alias ((path to desktop folder as text) & "Bkup:")

-- Get references to the files
tell application "Finder"
	try
		set tFiles to files of entire contents of sourceF as alias list
	on error -- only one file
		set tFiles to entire contents of sourceF as alias as list
	end try
	-- Duplicate then move them
	repeat with F in tFiles
		duplicate F to folder bkupF
		move F to folder destF
	end repeat
end tell

With respect to “English” vs “Danish”, you should use whatever language you have declared.

In the Script Editor, you can construct the proper paths as follows: In a new script window, type (the part in red): posix file " , then drag the folder to be targeted to the script window. Click the Alias button in the dialog that appears, close the quotes on the text that appears, and compile it. Change the word file that appears to alias and you’ve got a proper reference to the folder as your machine sees it. Copy that to your script.

ok, got a little futher, but the script only works when I run it in the editor…

I have this run when i dump a image to my folder:


on adding folder items to this_folder after receiving these_items
	do shell script "~/Scripts/jhead.sh"
end adding folder items to

and that works fine.
but where should I add this then:


	set sourceF to alias "Macintosh HD:Users:martin:Pictures:Nye_Billeder:"
	set orgF to alias "Macintosh HD:Users:martin:Pictures:Original:"
	set newF to alias "Macintosh HD:Users:martin:Pictures:Nye_til_galleri:"
		
	tell application "Finder"
		try
			set tFiles to files of entire contents of sourceF as alias list
		on error -- only one file
			set tFiles to entire contents of sourceF as alias as list
		end try
		-- Duplicate then move them
		repeat with F in tFiles
			duplicate F to folder orgF
			move F to folder newF
		end repeat
	end tell

This last script works if I run it in the editor but not when i include it in the first one… I would like to have the dublicate/move routine run after the shell scripts…

Martin

I don’t understand how your shell script works if you drop a collection of files or a folder on the activated folder. It makes no reference to the file that I can see unless that reference is embedded in the script. If so, what does the script do to identify files dropped - does it simply do its job to every file in the activated folder? In the script below, I’ve left that to you. In my part, I’ve assumed that whatever is dropped, it is always file or files; never a folder. I haven’t tested this, but it’s of the right form. If it errors, tell me what it says.


property sourceF : alias "Macintosh HD:Users:martin:Pictures:Nye_Billeder:"
property orgF : alias "Macintosh HD:Users:martin:Pictures:Original:"
property newF : alias "Macintosh HD:Users:martin:Pictures:Nye_til_galleri:"

on adding folder items to tFolder after receiving tItems
	do shell script "~/Scripts/jhead.sh" -- no ideas about this
	tell application "Finder"
		-- Duplicate then move them
		repeat with F in tItems
			try
				duplicate F to folder orgF
				move F to folder newF
			on error e
				display dialog e
			end try
		end repeat
	end tell
end adding folder items to

Yes! It simply runs a command “jhead” wich renames jpgs from their exif data… I run it on all files in the folder like this “jhead -blablabla *.jpg”… No need to pass every single filename from applescript to jhead when the renamed files should be moved right afterwards…

But it still dosn’t work, no errors to be seen…
It renames the files, and then nothing…

Could it be that it tries to duplicate/move the files WHILE the jhead command is running (takes a while if there’s alot of images)… so that it can’t figure out the filenames?

martin

Yes. One problem with ‘do shell script’ is that there is no intermediate feedback - the AppleScript containing the do shell script command continues immediately after the do shell script is passed to the shell unless an error comes right back. Also, have you checked with the contextual menu item (right click on the folder) ‘Configure Folder Actions’ that the folder action is active? I’ve been taking that for granted. If you comment out the shell script and drop a single file on the folder does it get duplicated and moved?

Just as well it does not trigger now. When you rename a file in an ‘activated’ folder, the folder action triggers again - it is a new file to the FA, and you end up in an infinite loop. The usual process is to move the file first to another folder and then continue from the script to process the file for a name change while the file is there. In your case, you might have jhead make that transfer as it processes each file. In the meantime, the Folder Action could ‘watch’ that folder’s size, and when it had been stable for longer than your process ever takes, begin duplicating and moving those files. Waiting goes like this:


set tFolder to choose folder -- as an example
set Size_1 to size of (info for tFolder) -- get initial size
delay 3 --wait 3 seconds, or whatever
set Size_2 to size of (info for tFolder) -- get a newer size, perhaps bigger
-- repeat until sizes match
repeat while Size_2 ≠ Size_1 -- if they don't equal, loop until they do
	set Size_1 to Size_2 -- new base size
	delay 3 --wait three seconds, or whatever
	set Size_2 to size of (info for myFolder) -- get a newer size
end repeat -- once the sizes match, the files are all in
-- continue with the duplicating and moving of files from tFolder
-- delete the originals in the active folder. 

Another common problem, however, is that Folder Action scripts will begin processing scripts when triggered and miss the end of a large list that has been dropped. Delays help, but my usual practice is to promptly abandon the folder action approach and instead use a stay-open ‘on idle’ script to do the work.

If you have not used them before, they go like this:


on run
	-- do setup - this runs when the application is started to set things up.
	-- It is not necessary to have an 'on run' handler. The on idle
	-- handler runs for the first time immediately after this anyway. If you want this to
	-- run all the time after every login, list it your startup items.
	-- Quit it from it's dock icon.
end run

-- 'on idle' runs immediately following the 'run' handler if there is one, and
-- thereafter on the interval specified.
--  (An 'on run' handler is not required, so omit if there is no setup)
-- In this section, you would see if there were any files in the target
-- folder, and if there are, process them.
on idle
	-- In this section, you do your script operations every interval
	return xx -- do this every xx *seconds*.
end idle

on quit
	-- do stuff - assumes you want to clean things up or save
	-- preferences or variables before the program quits. This section
	-- runs only if the application is quit from the dock, or by any
	-- other means.
	
	-- if there is an on quit handler, then 'continue quit' must
	-- be the last statement or the script will not stop!
	-- The presence of an 'on quit' handler 'intercepts' the
	-- system command to stop, so it will not complete the
	-- quit process until notified to continue. 'continue quit'
	-- does that.
	continue quit
end quit

Like adam I can not test this fully.

But the reason I think adams may not be working is because its looking for the original file names to move.
Although it should pop up an error?
also it is most likely that the script will run twice because the the folder action will see the renamed files as
new files.

**EDIT, Ah I see adam has replied while I was testing and has spotted the issue with the folder actions.
This is what I was going to post but realised the folder action repeat issue

 property sourceF : alias "Macintosh HD:Users:martin:Pictures:Nye_Billeder:"
 property orgF : alias "Macintosh HD:Users:martin:Pictures:Original:"
 property newF : alias "Macintosh HD:Users:martin:Pictures:Nye_til_galleri:"

on adding folder items to tFolder after receiving tItems
	do shell script "~/Scripts/jhead.sh" -- no ideas about this
	repeat with F in tItems
		my _wait()
	end repeat
	
end adding folder items to

on wait(F)
	
	if (exists F of sourceF) then
		my _wait()
	else
		tell application "Finder"
			try
				duplicate items of tFolder to folder orgF
				move items of tFolder to folder newF
			on error e
				display dialog e
			end try
			--
		end tell
	end if
end wait


property sourceF : alias "Macintosh HD:Users:martin:Pictures:Nye_Billeder:"
property orgF : alias "Macintosh HD:Users:martin:Pictures:Original:"
property newF : alias "Macintosh HD:Users:martin:Pictures:Nye_til_galleri:"
on adding folder items to tFolder after receiving tItems
	repeat with F in tItems
		tell application "Finder"
			try
				set dup_file to duplicate item F to folder orgF
				set dup_file to dup_file as alias
				set dupe_posix_path to POSIX path of dup_file
				do shell script " jhead -n%Y%m%d-%H%M%S " & quoted form of dupe_posix_path
				
				
				set move_file to move item F to folder newF
				set move_file to move_file as alias
				set move_posix_path to POSIX path of F
				do shell script " jhead -n%Y%m%d-%H%M%S " & quoted form of move_posix_path
			on error e
				display dialog e
			end try
			--
		end tell
	end repeat
	display dialog move_posix_path
end adding folder items to

** just updated the script, but I see eatfishdk has given up.

**update2 - Tested Fully and works
MAKE SURE you put the correct path to jhead
do shell script " /Users/USERNAME/PATH/jhead -n%Y%m%d-%H%M%S " & quoted form of move_posix_path

Yep, it does…

But lets stop here…
i thought that it was going to be easy to do in applescript! :smiley:
But I can see that it’s more complicated than that…
The problem can actually be done easy from within the shell script i’m already running, using the rm and cp command to move and copy files in a way that I can figure out… applescript simply makes no logic to me… maybe in time…

But thanks alot for all your help anyway!

Martin

Just tested the script fully and it works.

That makes the most sense too. You can still trigger your shell script from a folder action if you want to, but don’t have the timing issues that arise when a shell script takes off as a separate thread and the AppleScript immediately continues to the next instruction. To do this entirely within AppleScript, you need an application that understands EXIF (like GraphicConverter which has a ‘get EXIF’ command, while Image Events, QuickTime, and iPhoto do not).

Good luck.

Wow. :wink:

You downloaded and installed jhead from sentex, I assume. I don’t have it - I use GraphicConverer for such things.

Yes , Thought I would risk it. :wink:

Seems my last post got lost…

But in the new script that works the problem is that jhead gets run twice… on one images thats not so bad but on 50, 100 or even 500 this is (of cause) gonna double the amount of time… Thats why I placed jhead to be this first thing to run…

Martin

Worse than you think: jhead is run twice for every JPEG because it is inside the repeat, which is not quick. The problem with doing it in advance for all files ahead of the moving and duplicating is that jhead does not return a reference to the file with the changed name, so there’s no way of locating it in either folder after files are put there by jhead unless they are handled one at a time, once for each operation. The only thing that could help would be if either the ‘move to’ or the ‘backup to’ folder was empty to begin with, then the repeat loop could start from there. Otherwise, you have to separate the new ones from what was there before by looking at their modification date and time which wouldn’t be blindingly fast either.

Good luck.

[EDIT] A final possibility occurs to me which I can’t test. Put a temp folder inside the action folder, and return all the files to it. When that folder stops growing, move and duplicate the files from there to where they are to go. That folder would have to be empty to begin with, so you couldn’t just keep dumping batches into the active folder.

Doing the whole thing from a shell script is looking good. Let jhead load them into a temporary folder, then duplicate and copy them from there.