Move set number of files (with variable names) from set folder to variable folder

Hello

I'm looking for a neat solution to the following workflow, I think it's going to have to be scripted and unfortunately that surpasses my knowledge so I was hoping for some advice :smiley:

I'm currently running a large macros, but it's clunky and relies a lot on the UI. Part of it involves moving 24 files (file names are integers, it's always the first 24 from the folder that are moved) from one folder (fixed, on an external drive) to a folder that has been created (the path is always the same, but the folder name is set to a variable earlier in the process). Due to automating the opening of the finder window, selecting the first 24 files in the folder, opening up the new folder and moving the files that way, it's quite time consuming and doesn't allow the rest of the process until it's completed. As the macros is looped sometimes 12 times and the files are quite large, hanging on until the progress window has disappeared can add 10 mins plus to the whole process.

Now without the lengthy explanation -
Need to move files 1-24 from fixed folder a, to variable folder b. Files have a different name each time.

Is this something that can be automated/scripted?

Thanks for any advice in advance!

Hey Adam,

  • What's the path to your fixed folder?
  • What's an example path to your variably named folder?
  • How many files are in the fixed folder?
  • Approximately how big are the files in question?

-Chris

In addition to @ccstone's questions: Can you post some example file names? Are they eg "1-Myfile".."24_Myfile" or "01_Myfile".."24_Myfile"? Coz the second makes life a lot easier (ASCII sort, FTW!).

Does the macro need to process the files after they've been moved, or does it go on to other things not involving those files? Is it actually a "move" (ie within the same volume), a copy (ie from one volume to another, keeping the original), or a "copy-then-delete-original"? (It sounds like it's either the second or third, as a single volume "move" should be very quick.)

Thanks for the questions!

This is the set path for the folder that the files are in -
/Volumes/DRIVE 256/RNR/Master

The new folder is here -
/Users/adam/Final/variablefolder

The number of files in the fixed folder changes. It get loaded up with files which get processed each time, so could be in the 10s, or occasionally the 1000s.

The files themselves are usually around 30MB, and the name is always an integer, for example the first few in there at the moment are -
0048645
0048690
0048736
0048784
0048853

It is essentially a copy and delete task, you are correct.

Thanks again :slight_smile:

Assuming that the files are as per your example and "the first 24" is "the first 24, by name, using ASCII sort order" here's something you could try. It is destructive since it includes the delete step, so work on copies of your files!

Make a new folder on the "DRIVE 256" volume and duplicate 30-40 sample files from your "Master" folder into it. Make a test destination folder in /Users/adam/Final/

Copy the following into a new document in the Script Editor application:

tell application "Finder"
	set sourceFolder to (choose folder with prompt "Pick a source folder:")
	set destinationFolder to (choose folder with prompt "Pick a destination:")
	set sourceFiles to (items 1 thru 24 of (every item of sourceFolder sort by name)) as alias list
	repeat with eachItem in sourceFiles
		try
			duplicate eachItem to destinationFolder
		on error
			-- log an error here
			exit repeat
		end try
		delete eachItem
	end repeat
end tell

...and run it, choosing your test folder with the duplicate files in the first dialog and your test destination in the second. You'll get a Finder "bong" after every file is copied, just to let you know things are happening -- you may want to turn your volume down a touch while testing :wink:

I've done this one file at a time so you can handle an error on any file copy -- as written it will only delete a file after a successful copy and will exit the loop on an error, leaving you with some files copied (and deleted) and the rest not. Have a think about how you want to handle errors, whether you'd like successful copying to be logged to a file, etc.

If the script does what you want it's easy to include it as a KM action, feeding in the destination folder (and even the source, for portability) as a KM variable calculated earlier in the macro, and add improvements (like muting your sound for the duration!).

1 Like

Incredible, thank you Nige! Worked exactly as it should, particularly enjoying the bongs :slight_smile:

The next step for me is fixing the sourceFolder location (done in the script?) and somehow using the folderName var from KM to automate destinationFolder, which I feel maybe more complicated. I'm thinking for destinationFolder a text input popup that can be filled from KM, is that possible? Or is there an easier way?

I did try setting the sourceFolder location, however 8 days into learning swift and no knowledge of any other language, I wasn't even able to do that! Sorry for there being this barrier, I was really hoping I could take what you've given me already and run with it!

Many thanks once again!

If the source folder never changes, you should be able to set it this way:

set sourceFolder to POSIX file "/Volumes/DRIVE 256/RNR/Master"

In the spirit of @Nige-S's script, you can make this slight tweak to the code that handles the destination folder:

set destinationParent to POSIX file "/Users/adam/Final"
set destinationFolder to choose folder with prompt "Select or create a destination folder" default location destinationParent

This will bring up the folder picker dialog already in /Users/adam/Final and you'll be able to either select an existing folder or use the New Folder button to make and name a new one on the fly. This is, I think, more Mac-like (and more flexible) than using a Keyboard Maestro dialog to get the name of the new folder.

Building on this -- If you are anything like me, you'll frequently forget to turn on/plug in the external drive :wink:

set sourceFolder to POSIX file "/Volumes/DRIVE 256/RNR/Master"
set driveAvailable to ""
repeat while driveAvailable = ""
	try
		set driveAvailable to sourceFolder as alias
	on error
		display alert "Please plug in the external drive!" as critical giving up after 10
		delay 20
	end try
end repeat

...which flashes an alert if the volume isn't mounted, waits 20-30 seconds (depending on whether you manually dismiss the dialog), and tries again. If you're running this script unattended you might prefer to do something different if the volume isn't mounted, eg send an email to the "admin" and abort the macro.

I haven't got as far as dialogs in the KM manual yet, but would agree with the good Doctor -- for a standard Mac activity like choosing a file it makes more sense (and will be easier for you or another user) to use a standard Mac dialog.

But seeing @drdrang's name here reminds me of a point he often makes in his excellent blog[1] -- scripting isn't just about removing the tedium of doing something repeatedly by hand. It's also -- and perhaps more importantly -- about removing opportunity for user error. I would assume you've some logic to your destination folders' structure -- can you leverage that and calculate the destination within the script (or earlier in the KM macro), no user interaction required? Start by thinking about (or posting!) how the user currently chooses/creates the correct destination folder, and how you could use the data available to KM/AppleScript (eg current date and time) to replicate that -- or even improve on it!

[1] Being a newbie here, I'm unsure about the correctness of recommending another member's blog. Mods, feel free to edit/delete and chastise me. @drdrang -- if my fawning embarrasses you do let me know, but it really is an excellent blog...

2 Likes

Thanks again for all this help - I'm learning too which is great! The POSIX fix for sourceFolder is throwing up an error however, after selecting destinationFolder and trying to do the move...

error "Finder got an error: Can’t get every item of file "DRIVE 256:RNR:Master Test:"." number -1728 from every item of file "DRIVE 256:RNR:Master Test:"

Any ideas?
edit: I should add there are enough files in the folder :slight_smile:

The KM macro is meant to be run without any user input - the folder is generated earlier in the process in which the name is input from a variable, taken from a spreadsheet. There is no logic unfortunately, and as the folder is already created and new spreadsheets saved in it, we can't generate it at this point.

I'm not concerned about the ext drive not being connected as it's used for other purposes in the process so it'll have to be connected for the macro to run anyway, but that's a very good shout and I appreciate how you think of the little things like that!

As a possibility, I think a crude workaround to automating the destinationFolder selection could be when the destinationFolder dialog pops, KM typing the variable out which should select the correct folder.

Try coercing sourceFolder to an alias (which I forgot to do in my loop demo :frowning: ), eg:

set sourceFolder to POSIX file "/Volumes/DRIVE 256/RNR/Master Test/"
set sourceFolder to sourceFolder as alias

Then, since the information is already known, it's easy to add it in to the script logic. Assuming the saved destination folder name (just the name, not the path!) is in the KM variable "Folder Name" then add this at the start of the AppleScript we've been developing. Writing it out long-hand, so you can see each step:

tell application "Keyboard Maestro Engine"
set destFolderName to getvariable "Folder Name"
end tell

tell application "Finder"
	set destinationParent to "/Users/adam/Final/"
	-- combine the two strings, coerce to a POSIX path, and coerce that to a Finder alias
	set destinationFolder to (destinationParent & destFolderName) as POSIX file
	set destinationFolder to destinationFolder as alias

	set sourceFolder to POSIX file "/Volumes/DRIVE 256/RNR/Master Test"
	set driveAvailable to "No"
	repeat while driveAvailable = "No"
		try
			set sourceFolder to sourceFolder as alias
			set driveAvailable to "Yes"
		on error
			display alert "Please plug in the external drive!" as critical giving up after 10
			delay 20
		end try
	end repeat

	-- after all that, we get to do the copying!
	set sourceFiles to (items 1 thru 24 of (every item of sourceFolder sort by name)) as alias list
	repeat with eachItem in sourceFiles
		try
			duplicate eachItem to destinationFolder
		on error
			-- log an error here
			exit repeat
		end try
		delete eachItem
	end repeat
end tell

As always -- test with "disposable" files first, troubleshoot and tweak, and be certain you're happy before going into "production"! If you're having problems, post your macro.

1 Like

Sorry about messing up the setting of sourceFolder. Remembering when I need to add as alias is my AppleScript bête noire.

Thanks a lot, I really do appreciate all the help you've given me! I'll add it into the macro and run the whole thing to see how it does. No worries RE as alias, I didn't even know it was a thing until today :wink:

Hello again!

Sorry for the delay on getting back - tested it in the macro last night and it threw up an error, unfortunately working on other things today so was delayed on the reply.

Luckily that delay helped me see clearly. The error was -

text-script :992:992: script error:
Expected “given”, “with”, “without”, other parameter name, etc. but found end of script.

And the issue was.... human! I didn't select all on the script, so copied without the last few lines :expressionless: So in fact it works perfectly and is fully integrated now. Thanks so much for all your help, it really is much appreciated.

Now time to get my head into VBA for Excel to get rid of the endless keystroke actions.. Anyone know the directions to that forum? :face_holding_back_tears: