Move Last Download to Current Finder Folder

In my day job, I work on Windows, and XYplorer is my file manager of choice due to it’s configurability and extensibility through scripting. One of my most used extensions is one which will move the last downloaded file to the directory in the currently focused XYplorer pane. I have written about a very similar XYplorer script in the past that works in the same way, but rather than the last download, it grabs a copy of the last screenshot I took.

Recently I realised I was missing this functionality over on my Mac, and so I decided to redress the imbalance through a little scripting.

A Quick Script Solution

Shell scripts are ideal for moving files around. It is pretty much what shell scripting was invented for. So, it seemed like this was the obvious way to tackle this issue, but the scripting turned out to be a little more convoluted than I first imagined.

The basic operation can be expressed with a single move command, where I need to get the path of the last downloaded file ($lastDownloadPath), and build a path for the destination based on the current location in Finder.

# Move the file
mv "$lastDownloadPath" "$destinationPath"

Note that I’ve double quoted the variables to account for spaces in file paths, but now I needed to populate them.

Downloaded files are sent to my Downloads folder in my home directory, so to find the last downloaded file, I needed to scan the $HOME\Downloads directory and determine the last downloaded file. If we order the files in that directory by creation date, that will then give us the last downloaded file. The command I came up with to do this was as follows.

ls -pAt $HOME/Downloads | grep -v '/$' | head -n 1

The ls command carried out a listing of the Downloads folder. The -pArt options do the following:

  • p: adds a forward slash to the end of any entry that is a directory.
  • A: forces the listing to list all entries, including dot files.
  • t: specifies the base order as reverse chronological order of creation (/download).

The grep command receives the listing and then filters out any item that ends with a forward slash; this removes any directory from the listing.

Finally, the head command returns the first entry in the list giving us the file name for the last downloaded file.

I can use this to store the file name (for use with the destination path), and to build the last download path.

lastDownloadFile=$(ls -pAt $HOME/Downloads | grep -v '/$' | head -n 1)
lastDownloadPath=$HOME/Downloads/$lastDownloadFile

Now we need to get the current folder in Finder. At this point we are diverging into a graphical interface, so the shell is no longer looking like a great choice of solution. However, AppleScript allows us to interact with Finder, and we can run a little AppleScript from the command line via osascript.

The following line of AppleScript gets the path of the current folder being viewed in Finder.

tell application "Finder" to get the POSIX path of the (insertion location as text)

We can then place that in a variable using osascript, and combine this with the last download file name to generate the destination path for the move (mv) command.

finderCurrentFolder=$(osascript -e "tell application \"Finder\" to get the POSIX path of the (insertion location as text)")
destinationPath=$finderCurrentFolder$lastDownloadFile

The final script looks like this:

#!/bin/zsh

# Set-up variables
lastDownloadFile=$(ls -pAt $HOME/Downloads | grep -v '/$' | head -n 1)
lastDownloadPath=$HOME/Downloads/$lastDownloadFile
finderCurrentFolder=$(osascript -e "tell application \"Finder\" to get the POSIX path of the (insertion location as text)")
destinationPath=$finderCurrentFolder$lastDownloadFile

# Output paths to standard out in case we need to debug
echo FROM: $lastDownloadPath
echo TO: $destinationPath

# Move the file
mv "$lastDownloadPath" "$destinationPath"

Triggering the Script

While I could in effect run this from anywhere, I can have multiple Finder windows and tabs open, and to make sure that I am 100% clear on where files are being moved to, I decided to tie this to Finder and access it as a keyboard shortcut.

I have several of ways I could do assign it to a keyboard shortcut (wrap it in an AppleScript for FastScripts, add it as a script to Better Touch Tool or Alfred, create an Automator/Shortcuts quick action), but I opted for my standard tool for running these sorts of things - Keyboard Maestro. I simply created a new hot key triggered macro to a Keyboard Maestro group I have set up to only be accessible when Finder is the active app.

The shell script is executed via an Execute Shell Script action, and I originally added a Play Sound action as a notification to let me know when the move has completed. However, I decided that this was a poor choice, because it was not telling me if my move had completed successfully.

Instead I returned to the shell script and added an additional check for the exit code of the file move. The script then displays a visual notification appropriate to what happened, and I play a different sound depending upon whether the move completed successfully or not.

The final script looks like this.

#!/bin/zsh

# Generate a visual and auditory notification 
function notify
{
	osascript -e 'display notification "'$1'" with title "'$2'"'
	afplay "/System/Library/Sounds/$3.aiff"
}

# Set-up variables
lastDownloadFile=$(ls -pAt $HOME/Downloads | grep -v '/$' | head -n 1)
lastDownloadPath=$HOME/Downloads/$lastDownloadFile
finderCurrentFolder=$(osascript -e "tell application \"Finder\" to get the POSIX path of the (insertion location as text)")
destinationPath=$finderCurrentFolder$lastDownloadFile

# Output paths to standard out in case we need to debug
echo FROM: $lastDownloadPath
echo TO: $destinationPath

# Move the file
mv "$lastDownloadPath" "$destinationPath"

# Check the exit code and notify accordingly
mvStatus=$(echo $?)
echo Exit Code: $mvStatus

if [ $mvStatus -eq 0 ]; then
	notify "File Moved: $lastDownloadFile" "Move Last Download Here" "Tink"
else
	notify "Error, Exit Code: $mvStatus" "Move Last Download Here" "Glass"
fi

The ‘Move Last Downloaded File Here’ Keyboard Maestro macro is then set up like this.

Summary

What I thought was probably going to be a trivial shell script quickly became something more complicated, but not so much so that it was beyond reach. It may be that I could have done something equivalent in Keyboard Maestro without resorting to scripting, but I think in the end the solution I came up with is logical, maintainable, and with any luck, robust. It was also at least a little bit fun to put together and fills a nice little gap in my Mac workflow that I plugged on Windows years ago.

Author: Stephen Millard
Tags: | keyboard maestro | shell |

Buy me a coffeeBuy me a coffee



Related posts that you may also like to read