Getting the URL of the File Most Recently Added to a Folder

Hey Peter,

I think that's highly desirable.

(The breakage won't be too hard to fix.)

-Chris

1 Like

Hey JM,

Why specifically?

The folder action script will return aliases, and you can use the Finder to coerce those to file-URLs.

Then you'd have to trigger a Keyboard Maestro macro from the AppleScript.

And you'd have more than one script/macro to maintain.

Not to mention that Folder Actions suck until El Capitan (supposedly they've finally been fixed, but I have not yet verified this.)

-Chris

Because:

  1. KM does not return the full path of the file that triggered the add
  2. KM does not provide a direct means of getting the URL

I don't see any maintanance difference between KM calling an AppleScript, or an AppleScript calling a KM macro.

It's just another tool in your toolbox. Choose whichever works best for you.

Hey JM,

You've used Folder Actions? They are rather awkward.

While some folks have had quite good luck with them, I (and many others) have found them to be very error prone in the past. I have also found them to make the Finder more prone to crashing.

However this does NOT mean I won't use them if they're the right tool for the job now they've been made more reliable.


###applescript Release Notes: OSX 10.11 Changes
Folder Actions now reliably notices all added and removed items in an observed folder.


Point 1 is dead simple to work around in Keyboard Maestro.

Point 2 is a stickier wicket, as Keyboard Maestro's encoding schema doesn't produce exactly what the Finder would.

I'll probably write a plugin to get around this soon. In the meantime it can be done with AppleScriptObjectiveC, which is faster than using the Finder.

------------------------------------------------------------
use framework "Foundation"
tell application "Finder" to set fileList to selection as alias list
repeat with i in fileList
  set posixPath to POSIX path of i
  set contents of i to (current application's class "NSURL"'s fileURLWithPath:posixPath)'s absoluteString() as text
end repeat

fileList
------------------------------------------------------------

As far as I know the single biggest advantage Folder Actions has over Keyboard Maestro's Folder Trigger is that it harvests all items added (as a batch) at once, so they can be operated on as a batch. This would probably be meaningless in the downloads folder, but it could be very useful in a folder where files are dragged and dropped en mass.

KM runs once per file added.

-Chris

1 Like

Chris,

I've had nothing but good luck with AppleScript Folder Actions. I have a Evernote Import folder action that I use several times a day, and it has never failed or crashed.

Hey Folks,

I’ve added a boolean to this allowing folders to be included or excluded from the result.

-Chris

---------------------------------------------------------------------------------
# Auth: Christopher Stone { Heavy Lifting by Shane Stanley }
# dCre: 2016/02/09 06:58
# dMod: 2016/06/02 22:19
# Appl: ASObjC
# Task: Get the most recent item path from the designated directory 02.
#     : Allows for exclusion of folders.
# Tags: @Applescript, @Script, @ASObjC, @Get, @Most, @Recent, @Path
---------------------------------------------------------------------------------
use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
---------------------------------------------------------------------------------

# POSIX Path of the folder you're interested in.
set thePath to POSIX path of (path to downloads folder as text)

# Returns the POSIX Path of the last added item.
set sortedList to its filesIn:thePath sortedBy:(current application's NSURLAddedToDirectoryDateKey) includeFolders:false

---------------------------------------------------------------------------------
--» HANDLERS
---------------------------------------------------------------------------------
on filesIn:folderPOSIXPath sortedBy:sortKey includeFolders:includeFoldersBool
  # Specify keys for the values we want for each item in the folder:
  # We want the path, whether it's a directory, whether it's a package, and the key to sort on
  set keysToRequest to {current application's NSURLPathKey, ¬
    current application's NSURLIsPackageKey, ¬
    current application's NSURLIsDirectoryKey, ¬
    sortKey}
  # Make an NSURL for the folder because that's what's needed
  set theFolderURL to current application's class "NSURL"'s fileURLWithPath:folderPOSIXPath
  # Get a ref to the file manager
  set theNSFileManager to current application's NSFileManager's defaultManager()
  # Get list of NSURLs of items in folder, getting the values for our keys at the same time, and skipping invisible items
  set listOfNSURLs to (theNSFileManager's contentsOfDirectoryAtURL:theFolderURL ¬
    includingPropertiesForKeys:keysToRequest ¬
    options:(current application's NSDirectoryEnumerationSkipsHiddenFiles) ¬
    |error|:(missing value))
  # Create an array to store just the key values in
  set valuesNSArray to current application's NSMutableArray's array()
  # Loop through retrieving key values, adding each set as a dictionary/record to the array/list
  repeat with oneNSURL in listOfNSURLs
    (valuesNSArray's addObject:(oneNSURL's resourceValuesForKeys:keysToRequest |error|:(missing value)))
  end repeat
  
  # Filter out all directories that aren't packages using a predicate
  if includeFoldersBool ≠ true then
    set theNSPredicate to current application's NSPredicate's predicateWithFormat_("%K == NO OR %K == YES", current application's NSURLIsDirectoryKey, current application's NSURLIsPackageKey)
    set valuesNSArray to valuesNSArray's filteredArrayUsingPredicate:theNSPredicate
  end if
  # Make a sort descriptor that describes the key to sort on
  set theDescriptor to current application's NSSortDescriptor's sortDescriptorWithKey:(sortKey) ascending:true
  # Sort the array
  set theSortedNSArray to valuesNSArray's sortedArrayUsingDescriptors:{theDescriptor}
  
  # Extract just the paths and convert to an AppleScript list
  # return (theSortedNSArray's valueForKey:(current application's NSURLPathKey)) as list
  
  # Or if you only want the most-recent, use this instead of the previous line:
  return (theSortedNSArray's lastObject()'s valueForKey:(current application's NSURLPathKey)) as text
  
end filesIn:sortedBy:includeFolders:

# You can sort on other criteria, including: NSURLAttributeModificationDateKey, NSURLContentAccessDateKey, NSURLCreationDateKey, NSURLLabelColorKey, NSURLLabelNumberKey, NSURLLocalizedLabelKey, NSURLLocalizedTypeDescriptionKey, NSURLNameKey, NSURLTypeIdentifierKey, NSURLFileSizeKey, NSURLFileAllocatedSizeKey, NSURLTotalFileAllocatedSizeKey, and NSURLTotalFileSizeKey.

---------------------------------------------------------------------------------
3 Likes

Hey guys, I may be naive here, but what about a shell script? Like this:

ls -t "/Users/Dan/Documents/Keyboard Maestro/Work" | head -1

Hey Dan,

-t gives you a sort by modified date.

Unfortunately ls does not provide a means to find the last-added-item.

-Chris

I told you I might be naive! Well, it was worth a shot.

Hi,

I am using this script it takes up to 7 seconds on our systems.Get latest file URL.kmactions (1.3 KB)

set sourceFolder to (path to documents folder)

tell application "Finder"
   
   set fileList to (sort (get files of sourceFolder) by creation date)
   
   -- This raises an error if the folder doesn't contain any files
   -- Last File is the Most Recently Created --
   set theFile to (last item of fileList) as alias
   
   set thePath to POSIX path of theFile
   set oProp to (properties of theFile)
   set URLstr to URL of oProp
end tell

set strCMD to "osascript -l JavaScript -e '(strPath = decodeURI(\"" & URLstr & "\").slice(7)).slice(strPath.indexOf(\"/\"))'"
set strPosixPath to (do shell script strCMD)

Is there a way to just get the most recent added file faster? all I want is the most recent added to the Folder. Preferably at an instant speed without the code checking all files to find the most recent added. Does OS X Sierra allow for a faster method than what I am currently using?

You can do an Execute Shell Script action with something like this:

ls "$KMVAR_sourceFolder" -Urp | grep -v / | sort -ur | head -1

with the output going to a variable. This will not include folders, but will also not include packages and applications.

1 Like

Could you provide this as a shell script please? Sorry i am not coding savvy.

Just add an "Execute a Shell Script" action, and paste the command into it. Set it to "save results to variable", and enter a variable name. Like this:

:slight_smile:

1 Like

Thank you for this. ?

Was that a statement or a question? :slight_smile:

Sorry i am writing from my iphone responding as an email with a smily face. I guess KM does not process them

1 Like

I now get this result :slight_smile:

/var/folders/ct/lsmxdhzn2hv4p378kqlxxf8c0000gn/T/Keyboard-Maestro-Script-744B68F0-8610-4B23-B9F1-57527CBB781E:0:4: script error: A “"” can’t go after this identifier. (-2740)

does not seem to work.

I am using:

ls “$KMVAR_sourceFolder” -Urp | grep -v / | sort -ur | head -1

I guess the question is, what is source folder?

“sourceFolder” is the name of the variable you showed in the original post. It should contain the path to the folder you want to examine.

1 Like

this will be on different imacs and the source folder has a different lcoation for each different iMac. But in all occassions we need to pull out the file from the Documents folder. This is always in the default place.

Every iMac has a different name so the initial location name would be different…

How can we overcome this problem?

Try this:

cd ~/Documents
ls -Urp | grep -v / | sort -ur | head -1
1 Like