Suppose I have a folder “ToSort” containing folders “Sorted” and “Unsorted” with the “Sorted” folder further containing folders with names that identify contents. (Excuse the ASCII art above).
I have written this script to move files dropped into the outermost folder into the appropriate inner folders:
-- A script to sort files into a folder into sub-folders by name prefix
set SortedFldr to (path to desktop as text) & "ToSort:SortedFiles:" -- containing sub-folders for the sort.
set filesToSort to (path to desktop as text) & "ToSort:" -- into which a jumble of files is dropped or moved.
set NotSorted to (path to desktop as text) & "ToSort:Unsorted:" -- folder for files that won't sort.
tell application "Finder"
-- do things that only need doing once
set unSorted to every file of folder filesToSort
set fileNames to name of every file of folder filesToSort
set fCnt to count of fileNames
--
set clientFolderList to every folder in folder SortedFldr
set clientFolderNames to name of every folder of folder SortedFldr
set fldrCnt to count of clientFolderNames
end tell
-- set up the sort parameters
set folderkeys to {}
repeat with j from 1 to fldrCnt
set end of folderkeys to (characters 1 thru 3 of item j of clientFolderNames) as string
end repeat
set filekeys to {}
repeat with k from 1 to fCnt
set end of filekeys to (characters 1 thru 3 of item k of fileNames) as string
end repeat
-- now the shuffle
repeat with f from 1 to fCnt
repeat with fldr from 1 to fldrCnt
if item f of filekeys = item fldr of folderkeys then move item f of unSorted to item fldr of clientFolderList
end repeat
end repeat
-- whatever is left in the folder wouldn't sort into the master folders in the sorted file folder
tell application "Finder" to move (files of folder filesToSort) to folder NotSorted
Simple enough, and it works if I drop files named “ABCtest”, “DEFtest”, “GHItest”, and “XYZtest” into the ToSort folder and run the script.
Now the question. It would be fairly straightforward to concatinate into a space-delimited string the names of the files and the folders and then use text item delimiters to find the matches, reconstruct the names of both and move them. Would that be faster? I apologize for not trying this for myself (I may yet), but curiosity leads me to ask.
I also realize that if I were a dab hand at regex, I could do this all with a shell script, probably faster, but I’m not.
property folderToSort : (path to desktop as Unicode text) & "ToSort:"
tell application "Finder"
launch
try
set foldersSubSort to folders of alias (folderToSort & "Sorted:") as alias list
count result
repeat with i from 1 to result
set thisFolder to item i of foldersSubSort
set thisSortKey to (text 1 thru 3 of (get name of result))
get (files of alias folderToSort whose name begins with thisSortKey)
move (result) to thisFolder without replacing
end repeat
move (files of alias folderToSort) to alias (folderToSort & "Unsorted:") without replacing
on error errorMsg number errorNum
display dialog "Error (" & errorNum & "):" & return & return & errorMsg buttons "Cancel" default button 1 with icon caution
end try
end tell
Here’s a slightly faster variation on Bruce’s script. It reads the folder names en masse and loops through the names, rather than looping through the folders and getting their names with individual reads of the disk. It also sticks with Finder references rather than coercing things to alias or alias list.
property folderToSort : (path to desktop as Unicode text) & "ToSort:"
tell application "Finder"
try
set sortedFolder to (folderToSort & "Sorted:")
set subfolderNames to name of folders of folder sortedFolder
repeat with thisFolderName in subfolderNames
set thisSortKey to (text 1 thru 3 of thisFolderName)
move (files of folder folderToSort whose name begins with thisSortKey) to folder (sortedFolder & thisFolderName) without replacing
end repeat
move files of folder folderToSort to folder (folderToSort & "Unsorted:")
on error errorMsg number errorNum
display dialog "Error (" & errorNum & "):" & return & return & errorMsg buttons "Cancel" default button 1 with icon caution
end try
end tell
I’m not sure I understand the concept behind Adam’s original question.
First off, thank you both - wonderful compression and efficiency. I learn something every time.
WRT Nigel’s “I’m not sure I understand the concept behind Adam’s original question.” ; I was playing with this - a script to present choose from list dialogs and answers that is modeled after a more compact version of another of his scripts and wondered if my sorter could be put in the same terms.
-- Text Item Delimiters for finding items in two lists.
set Name_Choices to ¬
{"Eve Adams", "John Elton", "Jonah Whalen", "Mathew Marks", "Etta Kett"} -- list of name choices
set Num_Choices to {"1342", "4434", "7721", "8812"} -- list of number choices
set The_Data to "Eve Adams 1342 John Elton 4434 Jonah Whalen 7721 Mathew Marks 2465 Etta Kett 8812" -- the Name followed by the number that goes with them. Easy to set up from the two original lists or vice-versa.
set theType to (button returned of (display dialog "Choose which you want to enter" buttons {"Cancel", "Number", "Name"}) is "Name") -- true for Name, false for Number
if theType then
set choice to choose from list Name_Choices with prompt ¬
"Whose Number do you want?" without multiple selections allowed and empty selection allowed -- the user chooses a name
else
set choice to choose from list Num_Choices with prompt ¬
"Whose Name do you want?" without multiple selections allowed and empty selection allowed -- the user chooses a number
end if
if choice is false then error number -128 -- User selected "Cancel"
copy choice as string to Chosen -- save the choice for answering dialog ("choice" going to be changed).
(*
The following uses text item delimiters set to the choice to divide the data set into two parts - everything before the choice and everything after it. The first "word" of the last text item is a number given a two-part name and the last two words of the first text item are a name given a number:
*)
set astid to AppleScript's text item delimiters -- save the old delimiters
set AppleScript's text item delimiters to choice
if theType then
set choice to first word of last text item of The_Data
else
set choice to words -2 thru -1 of first text item of The_Data
end if
set AppleScript's text item delimiters to space
display dialog Chosen & " is " & choice
Ah. I think I see what you mean. It’s probably do-able, but I’m not sure it would be as good as Bruce’s approach. The file names would have to be separated with a delimiter that wasn’t likely to be in any of them (a space might not be suitable here), the relevant bits would have to be extracted and stuck back together, and finally the selected names would have to be reassociated with the relevant files for the move. The final stage would probably be something like ‘move every file of folder folderToSort whose name is in theseFileNames’, which is more or less the same effort as ‘move every file of folder folderToSort whose name begins with thisSortKey’ anyway.
That seems a very effective way to avoid using a repeat, provided that your delightfully-named people always have two words in their names. (“Ella Fantsfoot-Umbrellastand” would be OK in a string, but not as Unicode text.)
Apart from the missing string in Num_Choices, I’d like to suggest the following slight revamp of the last section. (The changes are to the range reference in the ‘else’ block and to the final setting of the TIDs.)
set astid to AppleScript's text item delimiters -- save the old delimiters
set AppleScript's text item delimiters to choice
if theType then
set choice to first word of last text item of The_Data
else
set choice to text from word -2 to word -1 of first text item of The_Data
-- or: set choice to text (word -2) thru (word -1) of first text item of The_Data
end if
set AppleScript's text item delimiters to astid
display dialog Chosen & " is " & choice