Move the Last Added Folder from a Target Folder to a Different Folder

Hello @ccstone, @peternlewis,

I've created an AppleScript that will pass the name of the last created folder to a variable. Now I'm trying to use that variable to move that folder to another folder. I'm appending the variable to file path which works for a copy and rename action, but doesn't seem to work for a move action.

This copy and rename action works. The defined variable is inside the red box after the file path:

However, it doesn't seem to work when I appended a variable to the file path for a move action. It's the last move action:

Here is the actual folder:

not_moving_folder

You can see that the error message is correctly identifying the folder's name from the variable appended to the file path, but says it doesn't exist:

Move file /WORKSPACE/DR_PROJECT_BUS/RIPPLE_PROJECT_BU/COLOUR_LAB_AI April 10, 2021 5/12/34 PM failed with Error Domain=NSCocoaErrorDomain Code=4 "“34 PM” couldn’t be moved to “Projects” because either the former doesn’t exist, or the folder containing the latter doesn’t exist." UserInfo={NSSourceFilePathErrorKey=/WORKSPACE/DR_PROJECT_BUS/RIPPLE_PROJECT_BU/COLOUR_LAB_AI April 10, 2021 5/12/34 PM, NSUserStringVariant=(
Move
), NSDestinationFilePath=/WORKSPACE/DR_PROJECT_BUS/RIPPLE_RESTORE/Resolve Projects/Users/guest/Projects/34 PM, NSFilePath=/WORKSPACE/DR_PROJECT_BUS/RIPPLE_PROJECT_BU/COLOUR_LAB_AI April 10, 2021 5/12/34 PM, NSUnderlyingError=0x60000eb94ae0 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}

Here is the macro:
DR_MOVE_RIPPLE_PROJECT_BU_TO_RESTORE_DATABASE.kmmacros (5.0 KB)

I don't understand,
Thanks!

Hey Ernest,

I don't want to fool with this, unless you really can't figure it out yourself.

Three things:

  1. Since you're using AppleScript anyway then use it for everything.
  1. Don't use the AppleScript method you're currently employing to sort by creation-date – it's notoriously slow – especially as the number of items in the given folder increases.
  2. If you must use Keyboard Maestro to copy and move items – NEVER assemble paths within the copy/move actions. It makes debugging atrocious.
    • Always assemble paths in a text variable, so you can open it in a display-text action to eyeball the path. Paths are tricky beasts, and little things can disrupt them.

-Chris

Hi @ccstone, no worries! Thanks for all your help! I usually figure it out eventually.

If you get bored, the main question is why this works when copying but not when moving folders:

/Filepath/%variable%

However, I see your point three, and assume I shouldn't be doing this in a move or copy action.

  1. Since you're using AppleScript anyway then use it for everything.<>

I would if I could, just an end user trying to make things go faster. I use Applescript only when I can't find or figure out the function in KM.

  2. Don't use the AppleScript method you're currently employing to sort by creation-date – it's 
  *notoriously* slow – especially as the number of items in the given folder increases.
  * [How to find the last item added to a folder using AppleScriptObjC ] 
  (https://forum.keyboardmaestro.com/t/getting-the-url-of-the-file-most-recently-added-to-a- 
   folder/2902/19).

I saw your script in my research. Your script looked complex with lots of variables to set. Sometimes it's easier for Noobs like me to try the script if the script had actual file paths, and nothing in the script other than what's required. Even if the paths are dummy paths. Just so that the syntax and formatting is all there, and a Noob can plug in their own paths and variables.

I'm not sure what to put if anything in just this one line:

(valuesNSArray's addObject:(oneNSURL's resourceValuesForKeys:keysToRequest |error|:(missing value)))

In any case, this is a temp back up folder that would be cleared at the beginning of each session. So there wouldn't be more than a couple hundred folders to search at the root of the folder. Would be nice if it was the fastest it could be though.

  3. If you must use Keyboard Maestro to copy and move items..

I like using KM to copy or move items because the macro will wait until KM is done copying (for sure) or moving (I assume) before moving on to the next task. Is it not OK to use KM to copy and move? I was trying finder, but in an earlier post you had said it was anything but easy to have a macro wait for a finder level copy.

  – NEVER assemble paths within the 
  copy/move actions. It makes debugging atrocious.
  * Always assemble paths in a text variable, so you can open it in a display-text action to eyeball the 
  path. Paths are tricky beasts, and little things can disrupt them.

Not sure I totally understand. Do you mean don't do this something like this?:

move_variable

Or this?:

copy_variable

I assume you mean don't use /FilePath/%variable% inside the move action?
I'll look for another way to do that.

Thanks!

Hey Ernest,

There's only one thing for the user to set in that script:

set thePath to POSIX path of (path to downloads folder as text)

I have the above set to the downloads folder of the current user.

To add a custom path:

set thePath to "/posix path/to your target directory/"

Here's a working script where you need to look for the 2 user settngs:

--» USER SETTING: TARGET DIRECTORY
--» USER SETTING: DESTINATION DIRECTORY

And emplace the POSIX Paths to the appropriate directories.

Both Full /POSIXPath/yourPath/ and ~/your/Path (tilde-path-notation) are supported.

-Chris


Move the Last Added Folder from a Given Directory to the Designated Directory v1.00.kmmacros (7.0 KB)

@ccstone,

I have no idea how this script works. But it does. Thank you so much!

I now have a clearer idea of how to implement your sample scripts. You have been kind enough to provide user input lines. I was thinking I had to learn how to adjust things further down in the script.

Thank you again!

:sunglasses:

Nor should you – AppleScriptObjC is very complicated compared to vanilla AppleScript.

I'm still a relative novice with it, and I've been an expert AppleScripter for over 20 years.

Normally when I write AppleScripts for people on this forum I put the user-settings in Keyboard Maestro set-variable actions for their convenience – but not always.

-Chris

Hey Ernest,

I wrote a macro to do this with only Keyboard Maestro actions:

Get The Path To The Last Folder Added to a Target Folder

It will be easier for you to wrap your head around than the AppleScriptObjC.

-Chris

Hi @ccstone,

Thank you so much for this! Staying all KM is faster. Why is that? I notice when I combine applescript and KM commands in a macro it's always just a little slower. Not a deal killer, but just a little noticeably slower.

I understand now about using variables for the move function instead of path.

Thanks also for the debugger actions. I'll amend those to test other macros. The debugger helped me understand, I think, what's actually defining the folder that will be moved:

folder_to_move

I think what's confusing for Noobs like me, is that nothing really says the action is selecting one folder. It says "For each local_itemPath in these collections".
Then it has "by date added reversed". So in my mind it says I'll order the folder by last added items first, but I don't see how it says I'll then select the last item added.

It works wonderfully, I just wish I understood.

KM is so powerful, I think you guys could sell a book with much longer and more detailed explanations than the wiki.

This macro, along with one that auto backs up a project folder and timestamps the name will help me so much! Resolve doesn't really have retrievable iterative project backups in collaboration mode, because of something called live save (which is usually really helpful).

We just invented the fix, plus an auto-restore function! There is a major time saving action in Resolve that ripples color correction changes and offsets across many clips. But the action can't be undone, and can ruin an entire project.

Now with one button I can take the dangerous action, and protect myself at the same time.

Thanks again!

Hey Ernest,

The For-Each action is basically just a For-Loop in programming parlance.

Bash:

for theFile in file1 file2 file3
do
   command1 on $theFile
done

AppleScript:

set theList to {"one", "two", "three", "four", "five"}
set outputList to {}

repeat with listItem in theList
   set end of outputList to contents of listItem
end repeat

outputList

So – for each item in a given collection (list) of items – do something.

local_ItemPath is the variable name of the working item (in this case the path to a file).

The collection (list) is the paths of items in the given directory – with a twist – we're sorting by date-added and then reversing the sort – so the very first item in the list is actually the last item added.

This means we don't have to iterate through the entire list to find the last one – we only have to find the first one.

Make sense?

-Chris

I think it all makes sense, up until the point of selecting the actual folder to move.

I get that “For Each” and “Date Added Reverse” sorts the folder by last added item first.

I get the sense the local_ItemPath is somehow selecting the last added folder. I just don’t see the command to select it in KM.

Thanks for helping understand this.

Hey Ernest,

You understand the Items-In-A-Directory collection is just a list of file/folder paths – yes?

A $HOME-Based POSIX Path (Otherwise Known as Tilde-Path) – the ~/ characters are shorthand for your user home folder.

~/test_directory/Excel_Workbooks/

Is equivalent to the full POSIX Path:

/Users/myUserName/test_directory/Excel_Workbooks/

It can also be written as:

"$HOME/test_directory/Excel_Workbooks/"

The file paths of the items in that directory:

/Users/myUserName/test_directory/Excel_Workbooks/Spreadsheet_test_data.xlsx
/Users/myUserName/test_directory/Excel_Workbooks/Test Workbook – 1 Broken Column.xlsx
/Users/myUserName/test_directory/Excel_Workbooks/Test_01.xlsx
/Users/myUserName/test_directory/Excel_Workbooks/TEST_orig_EDIT.xls

It is never selected per se – the path string is extracted to the variable local_ItemPath.

That path is used to move the item later.

  • My macro that you reference grabs the full list of path strings of a directory sorted by date-added.
  • It then reverses that list, so the last-added-item is at the top of the list.
  • It then initiates a loop starting with the most recently added item.
  • It breaks out of that loop immediately after extracting the first path string, because it's already found what is needed.

There is no substitute for personal experience.

Spend a little time breaking things down into pieces you can understand – using the tools at hand.

For instance.

Let's say I (like you) don't understand this last folder in a collection business – we'll let's make a macro and figure it out.

Last Item Path in a Folder v1.00.kmmacros (6.9 KB)

Or you don't understand what “The items in a directory:” means.

So let's figure that out.

  • Keyboard Maestro won't let you directly add to a variable all of the path strings to the items in a directory (unfortunately).
  • So you have to loop through the “The items in a directory:” collection and add then to a variable one at a time, until you have a complete list.

Items In a Directory Listing.kmmacros (7.9 KB)

Run the macros and play with the settings for sorting the list.

Get a feel for it, instead of incomplete intellectual knowledge.

Spend a little time studying thing you don't understand like “a collection”:

programming what is a collection

Becoming more familiar with programming concepts will help you in your Keyboard Maestro and scripting journeys.

-Chris

The internal method used by KM to execute an AppleScript causes it to be slower than when the script is executed by other tools, like FastScripts.

It should be clear that the KM For Each action using a Folder Contents Collection will loop through each item in the target folder.

This IF/THEN Action causes KM to EXIT the For Each loop after the FIRST folder in the target Folder is selected. The first folder will be the last folder added.

Make sense?

Thanks @ccstone and @JMichaelTX,

From the beginning of the thread I saw that the For each action was ordering the folder.

But I haven’t used the loop action yet, so it never occurred to me that that’s how the folder could be defined. Light bulb!

I can see how the loop function will be valuable.

@ccstone, doing my best, but this stuff is complex. I’ve almost got what I need done though.

Thanks again guys!

1 Like