Auto File Sorting

Hello – I’m looking for a solution to move 100+ files into their respective folder, based on matching the last 4 characters (not including the file extension) with the last 4 characters of the folder. (The folders names have the same last 4 characters as the file names.)

For example, I would move Filename-ABC1.png and Filename-ABC1.eps to “Foldername - ABC1” while at the same time moving Filename-DEF5.png and Filename-DEF5.eps to “Foldername - DEF5” and so on.

There are 50+ folders / 100+ files, and these names change based on each batch of files/folders.

While Hazel does such things, it would require the need to create many separate rules for each one.

Any suggestions are welcome - thanks in advance.

This script does what you want but speed may be an issue. Also, it assumes that all of the destination folders are top-level folders in the same parent folder (viz. targetFolder). Both of these issues can be dealt with but it’s always best to start simple. It’s essential that you work with duplicate files/folders until everything is found to work properly.

on main()
	set sourceFolder to (path to desktop as text) & "Source Folder"
	set targetFolder to (path to desktop as text) & "Target Folder"
	
	tell application "Finder"
		set theFiles to every file in folder sourceFolder
		set theFolders to every folder in the entire contents of folder targetFolder
	end tell
	
	set ATID to AppleScript's text item delimiters
	set AppleScript's text item delimiters to {"."}
	
	repeat with aFile in theFiles
		set aFileBase to text 1 thru text item -2 of (aFile as text)
		set aFileKey to text -4 thru -1 of aFileBase
		repeat with aFolder in theFolders
			if text -5 thru -2 of (aFolder as text) = aFileKey then
				try
					tell application "Finder" to move aFile to aFolder
					exit repeat
				on error
					display dialog "The file " & quote & (name of aFile) & quote & " already exists"
					exit repeat
				end try
			end if
		end repeat
	end repeat
	
	set AppleScript's text item delimiters to ATID
end main

main()

Edit March 25, 2021. I edited this script to act recursively in setting the variable theFolders and to include some simple error notification. I also placed the script in a handler, which has a small technical advantage.

The following script addresses both of the possible issues with the above script. It uses System Events to make things move along more quickly and it uses ASObjC to recursively get all folders within the target folder. It should be noted that this script throws an error if a file already exists in the destination folder; some error correction should be added to deal with this.

use framework "Foundation"
use scripting additions

set sourceFolder to POSIX path of ((path to desktop as text) & "Source Folder")
set targetFolder to POSIX path of ((path to desktop as text) & "Target Folder")

tell application "System Events" to set theFiles to POSIX path of (every file in folder sourceFolder whose visible is true)
set theFolders to getFolders(targetFolder)

set ATID to AppleScript's text item delimiters
set AppleScript's text item delimiters to {"."}

repeat with aFile in theFiles
	set aFileBase to text 1 thru text item -2 of aFile
	set aFileKey to text -4 thru -1 of aFileBase
	repeat with aFolder in theFolders
		set aFolder to POSIX path of aFolder
		if text -5 thru -2 of aFolder = aFileKey then
			tell application "System Events" to move file aFile to folder aFolder
			exit repeat
		end if
	end repeat
end repeat

set AppleScript's text item delimiters to ATID

on getFolders(theFolder)
	set theFolder to current application's |NSURL|'s fileURLWithPath:theFolder
	set theFileManager to current application's NSFileManager's new()
	set packageOption to current application's NSDirectoryEnumerationSkipsPackageDescendants
	set hiddenOption to current application's NSDirectoryEnumerationSkipsHiddenFiles as integer
	set folderContents to (theFileManager's enumeratorAtURL:theFolder includingPropertiesForKeys:{} options:(packageOption + hiddenOption) errorHandler:(missing value))'s allObjects()
	set thePredicate to current application's NSPredicate's predicateWithFormat:"pathExtension == ''"
	set theFolders to folderContents's filteredArrayUsingPredicate:thePredicate
	return folderContents as list
end getFolders

Thank you VERY much, @peavine – this second script worked perfectly.

Model: Macbook Pro 2017
AppleScript: 2.7
Browser: Firefox 86.0
Operating System: macOS 10.14