Monday, May 25, 2020

#1 2020-05-17 12:20:11 pm

Dareios
Member
Registered: 2020-05-17
Posts: 2

Archiving image files using Applescript and Finder too slow

Hello,

My programming skills are limited. Applescript usually does what I want it to do. This post concerns file management. I need to create ZIP-archives of object image files.

I have a larger folder of JPG-files. The files are named already using an object number followed by underscore and a running number (z.B. Object1_01.JPG, Object1_02.JPG, etc.). I attempted to use Applescript and Automator to select for each object the respective files and use Mac's Archive to produce loss-free ZIP archives. The workflow then loops through the directory until all ZIPs are created and the original JPGs are moved into a subfolder called ZIPPED.

The problem I am having is that it works fine with 200 files, but takes ages for 2000 files. I read it may be an issue with Finder or that Finder is not destined to do what I want it to do.

My Workflow has two Applescripts, Applescript # 1:

Applescript:


on run {input, parameters}
   
   
   with timeout of 1000 seconds
       
       
       
       tell application "Finder"
           
           set sourcefolder to get selection as alias
           
           set theFiles to (sort files in sourcefolder by name)
           
           set t to (time string of (current date))
           
           
           set namearray to {}
           
           set theFilename to name of (select (first file of sourcefolder whose name contains "_01"))
           
           set myArray1 to my theSplit(theFilename, ".")
           set theBasename to item 1 of myArray1
           set theExtension to item 2 of myArray1
           
           set myArray2 to my theSplit(theBasename, "_")
           set musNo to item 1 of myArray2
           set theFace to item 2 of myArray2
           
           
           select (every file of sourcefolder whose name begins with musNo)
           
       end tell
       
       
   end timeout
   
   
   return input
   return musNo
   return sourcefolder
   return ResultFolder
end run


on theSplit(theString, theDelimiter)
   -- save delimiters to restore old settings
   set oldDelimiters to AppleScript's text item delimiters
   -- set delimiters to delimiter to be used
   set AppleScript's text item delimiters to theDelimiter
   -- create the array
   set theArray to every text item of theString
   -- restore the old setting
   set AppleScript's text item delimiters to oldDelimiters
   -- return the result
   return theArray
end theSplit


on dateformat(theDate)
   set {year:y, day:d, time:t} to theDate
   copy theDate to b
   set b's month to January
   tell (y * 10000 + (b - 2500000 - theDate) div -2500000 * 100 + d) as string
       set date_string to text 1 thru 4 & "-" & text 5 thru 6 & "-" & text 7 thru 8
   end tell
   return date_string
end dateformat

Then Automator, get selected Finder Items

Create Archive

Applescript # 2

Applescript:


on run {input, parameters}
   
   
   with timeout of 1000 seconds
       
       
       
       tell application "Finder"
           
           set theFiles to (get selection)
           
           set theFilename to name of item 1 of (get selection) as string
           
           set myArray1 to my theSplit(theFilename, ".")
           set theBasename to item 1 of myArray1
           set theExtension to item 2 of myArray1
           
           set myArray2 to my theSplit(theBasename, "_")
           set musNo to item 1 of myArray2
           set theFace to item 2 of myArray2
           
           
           
           
           set theArchive to (select (first file of container of item 1 of (get selection) whose name contains "Archive.zip"))
           
           set {theName, theExtension} to {name, name extension} of theArchive
           
           if theExtension is not "" then
               set theName to text 1 thru -((count theExtension) + 2) of theName -- just
               set theExtension to "." & theExtension
           end if
           
           set the name of theArchive to musNo & theExtension as string
           
           set currentDir to ((target of front Finder window) as text) as alias
           
           set outputFolder to POSIX path of (currentDir) & "ZIPPED"
           do shell script "mkdir -p " & quoted form of outputFolder
           
           set theFiles to select (every file of currentDir whose name begins with musNo and name extension is "JPG")
           
           set Zippedfolder to quoted form of outputFolder
           
           set TheFilesCount to number of items of theFiles
           
           move items 1 thru TheFilesCount of theFiles to folder "ZIPPED" of currentDir
           
           
       end tell
       
       tell application "Finder" to get (container of (path to me)) as text
       
   end timeout
   
   
   return input
   return musNo
end run


on theSplit(theString, theDelimiter)
   -- save delimiters to restore old settings
   set oldDelimiters to AppleScript's text item delimiters
   -- set delimiters to delimiter to be used
   set AppleScript's text item delimiters to theDelimiter
   -- create the array
   set theArray to every text item of theString
   -- restore the old setting
   set AppleScript's text item delimiters to oldDelimiters
   -- return the result
   return theArray
end theSplit


on dateformat(theDate)
   set {year:y, day:d, time:t} to theDate
   copy theDate to b
   set b's month to January
   tell (y * 10000 + (b - 2500000 - theDate) div -2500000 * 100 + d) as string
       set date_string to text 1 thru 4 & "-" & text 5 thru 6 & "-" & text 7 thru 8
   end tell
   return date_string
end dateformat

and finally a loop action.

Does anyone have an idea how to make this faster? Particularly important is loss-free Archiving.

Thanks for any suggestions!

Last edited by Dareios (2020-05-17 12:22:00 pm)

Offline

 

#2 2020-05-17 02:20:00 pm

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 4344

Re: Archiving image files using Applescript and Finder too slow

Below is a script doing some parts of the job very quickly.
Alas I have no free time available to apply your filter upon file names.

Applescript:

use AppleScript version "2.5"
use framework "Foundation"
use scripting additions

property |⌘| : a reference to current application

set theLib to choose folder -- Dossier à sélectionner

set theURL to (|⌘|'s NSArray's arrayWithObject:(theLib as «class furl»))'s firstObject()

set theManager to |⌘|'s NSFileManager's defaultManager()
-- build an URL pointing to the folder named "ZIPPED"
set theZIPPEDURL to theURL's URLByAppendingPathComponent:"ZIPPED"
-- create this folder
set {theResult, theError} to theManager's createDirectoryAtURL:theZIPPEDURL withIntermediateDirectories:true attributes:(missing value) |error|:(reference)
-- Now we have an URL to the final storage
set skipsPackageDescendants to |⌘|'s NSDirectoryEnumerationSkipsPackageDescendants as integer --> 2
set skipHidden to |⌘|'s NSDirectoryEnumerationSkipsHiddenFiles as integer --> 4
set theOptions to skipsPackageDescendants + skipHidden
set allURLs to (theManager's enumeratorAtURL:theURL includingPropertiesForKeys:{} options:theOptions errorHandler:(missing value))'s allObjects()
set theFormat to "(self.pathExtension =[c] 'jpg') OR (self.pathExtension =[c] 'jpeg')"
set thePredicate to |⌘|'s NSPredicate's predicateWithFormat:theFormat
set jpegURLs to (allURLs's filteredArrayUsingPredicate:thePredicate)
-- Now we have an array of NSURLs pointing to picture.jpeg files
repeat with anURL in jpegURLs
   set theName to anURL's lastPathComponent() as string
   -- insert here your code related to file names
   set maybe to theName contains "_01"
   set furl to (anURL as «class furl»)
   set origPath to POSIX path of furl --anURL's |path|() as string
   set turl to furl as string
   set zipPath to POSIX path of (turl & ".zip") --zipURL's |path|() as string
   do shell script "ditto -ck " & quoted form of origPath & " " & quoted form of zipPath
   set destinationURL to (theZIPPEDURL's URLByAppendingPathComponent:(anURL's |lastPathComponent|()))
   set {theResult, theError} to (theManager's moveItemAtURL:anURL toURL:destinationURL |error|:(reference))
end repeat

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) dimanche 17 mai 2020 22:19:55

Offline

 

#3 2020-05-17 10:12:04 pm

Dareios
Member
Registered: 2020-05-17
Posts: 2

Re: Archiving image files using Applescript and Finder too slow

Thanks a lot. I look into it!

Offline

 

#4 2020-05-19 11:38:24 pm

KniazidisR
Member
Registered: 2019-03-03
Posts: 1258

Re: Archiving image files using Applescript and Finder too slow

Dareios wrote:

The problem I am having is that it works fine with 200 files, but takes ages for 2000 files. I read it may be an issue with Finder or that Finder is not destined to do what I want it to do.


The plain AppleScript (and not Finder) is slower than AsObjC. So, when you want to write effective plain Apple-script, you should avoid any unnecessary operations, especially if they are time-consuming. Let's begin with this code line:

Applescript:

set theFiles to sort files in sourcefolder by name

Sort operation is time consuming. I don’t see where you use its result further in the code. So it’s just useless with you. It can be thrown into the trash.

Now, let's see this code line:

Applescript:


set theFiles to select (every file of currentDir whose name begins with musNo and name extension is "JPG")

Selecting Finder items is time consuming. I don’t see where you use selecting result further in the code. So it’s just useless with you. It can be modified. No need selecting the files. It is enough getting references to this files:

Applescript:


set theFiles to every file of currentDir whose name begins with musNo and name extension is "JPG"

Now, this. Not so important. It is not time consuming, but is useless:

Applescript:


set t to (time string of (current date))
set namearray to {}

Last edited by KniazidisR (2020-05-20 12:09:24 am)


Model: MacBook Pro
OS X: Catalina 10.15.4
Web Browser: Safari 13.1
Ram: 4 GB

Offline

 

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)