Although this is a relatively simple AppleScript. It
still took me about a
day to write and test. And it has a long way to go before I feel it's
done.
For this first version, the objective was to copy one folder structure
to
another folder structure. The tricky part is to not copy unchanged
files,
which saves a huge amount of time. In testing, this is still a very
slow
script which takes about half an hour to run on my couple thousand file
web
sites -- even with no copying to do.
-- While items remain in queue, process each one repeat while ((length of l_pending_folders) > 0) -- Remove the first item from l_pending_folders set l_current_folder to first item of l_pending_folders if (length of l_pending_folders = 1) then set l_pending_folders to {} else set l_pending_folders to rest of l_pending_folders end if -- Log current folder log "Checking folder " & l_current_folder as string
As you can see, the outer loop cycles through folders. The inner loop
cycles
through the files of each folder. An alternative design is to have one
loop
where the queue is the files to process. If you process a folder add
its
contents to the queue. That's a bad design because with my website I
quickly
end up with over a thousand files in the queue, which is quite a memory
hog.
-- Determine destination folder string set l_string to l_current_folder as string try set l_string to (text l_source_length through (length of l_string) of l_string) on error l_error -- error if this is the source folder base string set l_string to "" end try set l_string to l_destination_folder_string & l_string -- Determine destination folder. -- Note that destination folder must exist. set l_dest_folder to alias l_string
So l_pending_folders holds folder items. Theoretically I could
also
have a l_destination_folders queue to hold destination folders
and
then I wouldn't have to do the above. But that would mean another queue
with
dozens of items, versus a bit of a slowdown to do string manipulations.
I
chose to do the string manipulations, so why do I need to do it? Well,
based
on one folder object I can't easily pick the corresponding folder
object in
the destination hierarchy. So I extract the current folder as a path
like
"::". Then I strip out the source folder base
path
and replace it with the destination folder base path. Then I use the
string
to retrieve the corresponding destination folder.
Now, if the destination folder does not exist, I'll get an error and
without
a try...catch block the script stops. So why do I not need it? Well,
for the
root folder obviously the destination exists because the user had to
select
it at the start. Now, as we process each item in the source folder in
the
inner loop, if it's a folder we make sure the corresponding folder
exists in
the destination folder, otherwise we create it then. So by the time we
get
back to the outer loop we guarantee that the destination folder exists.
Well,
not quite. Someone else could always delete that destination folder
before
we get to it and we could have errored making the destination folder --
neither of which we take into account in this first version.
|