Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

How do I make this script faster?

Hi there!


I made my very first ever script in order to create several thousand QR Codes for my boss. The script works (most of the time) but the problem I’m having is the speed. The script takes 4 seconds to create one code, which is fine except for the fact that we will need to create 75,000 codes at one time. This comes out to a total of 83 hours to create them all! I have a few delays in my script and I have tried taking them out and shortening them but any more alterations causes the script to not work correctly. 😟 I’m sure that the script will look super newbish to pros like you guys but any suggestions would be grand.


The script:


on adding folder items tothis_folderafter receivingthese_items

repeat with an_item in these_items

tell application "TextEdit"


activate


openan_item


tell application "TextEdit"


activate

end tell

tell application "System Events"


keystroke "a" usingcommand down

end tell


tell application "System Events"


keystroke "c" usingcommand down

end tell


tell application "System Events"


keystroke "w" usingcommand down

end tell

delay 0.25

tell application "System Events"


keystroke "q" usingcommand down

end tell

delay 0.25

tell application "System Events"


keystroke "v" usingcommand down

end tell


tell application "System Events" to keystroke return

delay 0.25


tell application "Preview"


activate

end tell

delay 0.25

tell application "System Events"


keystroke "s" usingcommand down

end tell

delay 0.25

tell application "Preview"


activate

end tell

delay 0.75

tell application "System Events" to keystroke return


delay 0.5

tell application "System Events" to keystroke return

delay 0.25

tell application "System Events"


keystroke "w" usingcommand down

delay 0.25

end tell

end tell

end repeat

end adding folder items to





How it works:

The script relays on a couple factors. The “command q” shortcut triggers another script that makes the QR code, which I did not write:



set the theRes to "300"


display dialog "URL?" default answer "http://www.google.com"

set the theURL to the text returned of the result


set input to "http://chart.apis.google.com/chart?cht=qr&chs=" & theRes & "x" & theRes & "&chl=" & theURL


set input to quoted form of input


set temp_file to (path totemporary items)

set temp_name to do shell script "uuidgen"

set temp_file to (POSIX path of temp_file) & temp_name

set q_temp_file to quoted form of temp_file


set cmd to "curl -o " & q_temp_file & " " & input


do shell scriptcmd

set x to alias (POSIX filetemp_file)

tell application "Finder" to open x



My script works with this one using a text file that is placed in a folder with the script linked to it. I hope this is making sense, I’m sure it seems backwards and weird. To make a long story short, I need to somehow make this work faster and I am willing to rework the entire thing or go with a new idea entirely. Thanks in advance!


-Erin

iMac, OS X Mavericks (10.9.2)

Posted on Apr 17, 2014 4:46 PM

Reply
28 replies

Apr 17, 2014 5:12 PM in response to birdmadgirl7

Try to combine events. Each call to System Events takes time.


This is an example for part of your script:


tellapplication "System Events"


keystroke "a" usingcommand down


keystroke "c" usingcommand down


keystroke "w" usingcommand down

delay 0.25


keystroke "q" usingcommand down

delay 0.25


keystroke "v" usingcommand down


keystrokereturn

delay 0.25

end tell

tell application "Preview" to activate

delay 0.25

tell application "System Events" to keystroke "s" using command down

Apr 17, 2014 5:40 PM in response to birdmadgirl7

By plain text you mean just a .txt file, correct? Will report back, thanks for the help! 🙂


Yes. Instead of loading the text file in TextEdit, and doing ⌘A, ⌘C, then closing TextEdit, you can get the contents of the file into the clipboard with this one line:

do shell script "cat " & quoted formofPOSIX pathofan_item & " | pbcopy"

Apr 17, 2014 5:50 PM in response to Tony T1

Thanks!


Well, I made the adjustments you suggested but it's not working for me. The script appears to be getting to the step where te QR code is saved and closed in Preview but code is not actually created. Here is the code with adjustments, are they in the right places?




on adding folder items tothis_folderafter receivingthese_items

repeat with an_item in these_items

tell application "TextEdit"


activate


openan_item


tell application "TextEdit"


activate

end tell


do shell script "cat " & quoted formofPOSIX pathofan_item & " | pbcopy"

tell application "System Events"


keystroke "w" usingcommand down

delay 0.25


keystroke "q" usingcommand down

delay 0.25


keystroke "v" usingcommand down


keystrokereturn

delay 0.25

end tell

tell application "Preview"


activate

end tell

delay 0.25

tell application "System Events"


keystroke "s" usingcommand down

end tell

delay 0.25

tell application "Preview"


activate

end tell

delay 0.75

tell application "System Events" to keystroke return


delay 0.5

tell application "System Events" to keystroke return

delay 0.25

tell application "System Events"


keystroke "w" usingcommand down

delay 0.25

end tell

end tell

end repeat

end adding folder items to

Apr 17, 2014 6:49 PM in response to birdmadgirl7

You get an A for effort, that's for sure 😝


See If I understand what is going on:


  1. A file is added to a folder
  2. The file is opened in TextEdit
  3. the whole file is selected
  4. the selection is copied to the clipboard (really the selection is cut which places it in the clipboard).
  5. The QR script is run it does a display dialog, the contents of the clipboard is pasted into the dialog.
  6. The script goes off
  7. preview and other things happen.


That about right? So is it safe to assume that the files placed in the folder contain URLs. one per file?


If so you can simplify all this by taking the content of the file and putting it straight into the QR script. If you have access to that script you can even make it simpler.


Let me know if this is right or if I'm totally off base.

Apr 17, 2014 10:39 PM in response to birdmadgirl7

Scrub the entire UI scripting elements. Completely unnecessary, cumbersome and slow.


From what I can see, there are three elements to your script:


1) read the contents of the file

2) generate a temp file name

3) call a Google API passing in the file contents and writing the output to the temp file.


This should do that:


on adding folder items tothis_folderafter receivingthese_items


repeat with an_item in these_items


-- read the file contents:


-- (this one line replaces the entire 'tell application "TextExit" stuff

set theURL to readfilean_item



-- setup the API call:


set theRes to "300"


set input to "http://chart.apis.google.com/chart?cht=qr&chs=" & theRes & "x" & theRes & "&chl=" & theURL

set input to quoted form of input



-- there may be a better way of doing this, but if this is working for you, go with it:


set temp_file to (path totemporary items)

set temp_name to do shell script "uuidgen"

set temp_file to (POSIX path of temp_file) & temp_name

set q_temp_file to quoted form of temp_file


set cmd to "curl -o " & q_temp_file & " " & input



-- go make the API call and save the resulting file



do shell scriptcmd



-- this code here seems irrelevant, but if it works for you...

set x to alias (POSIX filetemp_file)

tell application "Finder" to open x


end repeat


end adding folder items to

What seems to be missing is any link between the original file and the QR image file.

I'm assuming that 'uuidgen' creates a unique file name. If that's the case, you save each URL in a unique file name, but you don't necessarily know the name of the image file or the QR code that it contains. This may or may not be an issue for you, depending on your use case. Personally I think I'd want some link between the two, but you may not care.

Apr 18, 2014 3:36 AM in response to birdmadgirl7

Hello


I can only guess your workflow from what I see in your script and if I guess correctly, I think you may use something like the following handler. Handler takes three parameters – input text file, resolution and output directory – and it will get data from input file, escape characters as required for uri and call google api via curl(1) to create QR code png image. Resulting png file is named after input file name without extension plus ".png" and saved in the specified output directory.


If you have different naming and saving scheme, please elaborate it. (I'd assume UUID is not the final name of QR code png file.)



set infile to (path to desktop)'s POSIX path & "Hello world.txt"
set outdir to (path to desktop)'s POSIX path & "QR_codes"

create_QR_code_for_file(infile, 300, outdir)

on create_QR_code_for_file(infile, res, outdir)
    (*
        string infile : POSIX path of input text file whose contents is to be converted to QR code
        integer res : resolution of resulting png
        string outdir : POSIX path of output directory

        * Data in infile is assumed to be UTF-8 text
        * Given infile = a.txt, output png file is saved as outdir/a.png
    *)
    set args to ""
    repeat with a in {infile, res, outdir}
        set args to args & ("" & a)'s quoted form & space
    end repeat
    do shell script "/bin/bash -s <<'EOF' - " & args & "
infile=\"$1\"    # source plain text file
res=\"$2\"        # resolution of resulting png
outdir=\"$3\"    # output directory

[[ -d \"$outdir\" ]] || mkdir -p \"$outdir\" || exit    # create outdir if not present
name=${infile##*/}
outfile=\"$outdir/${name%.*}.png\"

str_e=$(perl -CSDA -MURI::Escape -0777 -ne 'print uri_escape_utf8($_)' \"$infile\")        # uri escaped data of infile
req=\"http://chart.apis.google.com/chart?cht=qr&chs=${res}x${res}&chl=${str_e}\"
curl -s -o \"$outfile\" \"$req\"
echo $?
EOF"
    result as number
end create_QR_code_for_file


Hope this may help,

H



PS. In case, here's an example of folder actions script using the handler.


property outdir : (path to desktop)'s POSIX path & "QR_codes"

on adding folder items to d after receiving aa
    set donedir to (d's POSIX path) & "_DONE"
    repeat with a in aa
        set ret to create_QR_code_for_file(a's POSIX path, 300, outdir)
        if ret = 0 then
            move_file_to_directory(a's POSIX path, donedir)
        end if
    end repeat
end adding folder items to

on create_QR_code_for_file(infile, res, outdir)
    -- omitted (the same as above)
end create_QR_code_for_file

on move_file_to_directory(f, d)
    do shell script "dst=" & d's quoted form & "; f=" & f's quoted form & "
[[ -d \"$dst\" ]] || mkdir -p \"$dst\" || exit
mv -f \"$f\" \"$dst\""
end move_file_to_directory


Message was edited by: Hiroto (fixed perl code so that it uses uri_escape_utf8() in lieu of uri_escape())

Apr 18, 2014 3:05 PM in response to birdmadgirl7

OK good, I think we can speed this up a ton for you.


As you can see two others posted after me and supplied possible solutions. Both look reasonable but I would first try Camalot's solution as it is closest to what you are doing now and should be easier to maintain or modify if the need arises.


So select all the test in Camolot's post between the on adding statment and the end adding statement right click on the selected text and from the Services menu select make new Applescript like so


User uploaded file


Once that is done you need to save this as a folder action like you did with your original script.


Also look at Camalot's last paragraph and see if that applies.


Post back if you have more questions.


regards

Apr 18, 2014 3:10 PM in response to Hiroto

As I responded to someone else, I do have a naming convention which is the serials correspoding to the URL's and I have a spreadsheet contaning both of these factors. This is really great but I'm not sure how to get it to work, could you give me instructions on what to do with it? Sorry I'm such a newb! I attached it to the folder but nothing happens. :'(

How do I make this script faster?

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.