Kees
Kees

Reputation: 471

Moving entire folders with AppleScript

This is my very first use of AppleScript. I'm trying to use it to move a 100+ folders (and their content files) from one location to another. I'm not just moving the files because I want to maintain the filing system. So I've got the folders listed in a .txt file in this format:

Macintosh HD:Users:Tom:Music:iTunes:Afrika Bambaataa

Macintosh HD:Users:Tom:Music:iTunes:Air

And then I run the following in AppleScript:

tell application "Finder"
    set TextFile to (choose file with prompt "Select your text file" of type {"txt"})
    set My_Folder to (choose folder with prompt "Select your destination folder")
    set List_files to paragraphs of (read TextFile)
    move List_files to My_Folder
end tell

However the error I receive is the following:

error "Finder got an error: Handler can’t handle objects of this class." number -10010

Any help on what I'm doing wrong here?

Much appreciated!

Upvotes: 0

Views: 308

Answers (1)

CJK
CJK

Reputation: 6102

tell application "Finder"
    set TextFile to (choose file with prompt "Select your text file" of type {"txt"})
    set My_Folder to (choose folder with prompt "Select your destination folder")
    set List_files to paragraphs of (read TextFile)
    move List_files to My_Folder
end tell

Currently, List_files is just a list of text objects, i.e.

{"Macintosh HD:Users:Tom:Music:iTunes:Afrika Bambaataa",
 "Macintosh HD:Users:Tom:Music:iTunes:Air", ...}

so what you're asking Finder to do is move some text to a folder, which doesn't make sense. You need to tell Finder that this text represents a path to a folder, by using the folder specifier. Since this can't be done en masse, you have to iterate through the list:

repeat with fp in List_files
    move folder fp to My_Folder
end repeat

However, I wouldn't actually do it like this, as that will require 100+ separate move commands - one for each item in List_files. Instead, we'll edit the list items first by prepending the folder specifier to each item, and then move the list of folders altogether in a single command:

repeat with fp in List_files
    set fp's contents to folder fp
end repeat

move List_files to My_Folder

Depending how big the files are and how long the transfer will take, the script might time out before the transfer is complete. I'm not honestly sure what impact this would have on an existing file transfer. I suspect that AppleScript will simply lose its connection with Finder, but that the transfer will continue anyway since the command has already been issued (another benefit of using a single move command instead of multiples). But, if you want to avoid finding out, we can extend the timeout duration to be safe:

with timeout of 600 seconds -- ten minutes
    move List_files to alias "Macintosh HD:Users:CK:Example:"
end timeout

The final script looks something like this:

tell application "Finder"
    set TextFile to (choose file with prompt "Select your text file" of type {"txt"})
    set My_Folder to (choose folder with prompt "Select your destination folder")
    
    set List_files to paragraphs of (read TextFile as «class utf8»)
    
    if the last item of the List_files = "" then set ¬
        List_files to items 1 thru -2 of List_files
    
    repeat with fp in List_files
        set fp's contents to folder fp
    end repeat
    
    move List_files to My_Folder
end tell

The extra line that starts if the last item of... is just a safety precaution in case the last line of the text file is a blank line, which is often the case. This checks to see if List_files contains an empty string as its last item, and, if so, removes it; leaving it in would throw an error later in the script.

EDIT: Dealing with folders that don't exist

If the repeat loop throws an error due to an unrecognised folder name, then we can exclude that particular folder from the list. However, it's easier if we create a new list that contains only the folders that have been verified (i.e. the ones that didn't throw an error):

set verified_folders to {}

repeat with fp in List_files
    try     
        set end of verified_folders to folder fp
    end try
end repeat

move the verified_folders to My_folder

This also means we can delete the line beginning if the last item of..., as the check that this performs is now going to be caught be the try...end try error-catching block instead.

Upvotes: 1

Related Questions