What is the proper, efficient way to iterate over Reminders using AppleScript? The script below works as expected, but takes 18 seconds to iterate over 180 Reminders when run from the command line using osascript! (This same script takes only 2-3 seconds when run from within the ScriptEditor.)
# Find all Reminders whose name contains "Alumni"
set findMe to "Alumni"
set answer to "Maches: "
tell application "Reminders"
set names to name of every reminder
end tell
repeat with name in names
if name contains findMe then
set answer to answer & " --- " & name
end if
end repeat
return answer
I've run this script two ways from the command line: As a compiled script: osascript testReminders2.scrpt and as a text file: ./testReminders2.applescript (where this file begins with #! /usr/bin/osascript. Both versions take about the same amount of time.
Related
I'm a total newbie on Automator and Scripting...
I have read a lot of answers to problems a bit similar to mine, but I don't succeed to adapt with Automator + AppleScript.
Here is what I want to do:
When I download a file to a directory /Volumes/Macboot /Downloads, (yes there is a space in the HDD's name), e.g. statement_EUR_2020-05-01_2020-05-31.pdf.
I verify if the file is with extension pdf + it contains an IBAN + the name contains "statement".
If the file corresponds, I want to verify the year and month in the name and move it accordingly to the good Google Drive folder:
/Volumes/Macboot /Travail en cours/Google Drive/Company/Comptabilité/**2020**/**05**/Compte Transferwise 1/
Right now, I succeeded to obtain year and month in 2 variables, but I can't find a good way to move the file using variables in the next step in Automator.
The following should work, or at least get you on the correct path. Set the following for variables:
monthName: a text variable that holds the month value, as above
yearName: a text variable that holds the year value, as above
filePath: a storage variable that holds reference to the file you are working on
outputFolder: a storage variable that will hold a reference to the output folder
The first two actions collect the month and year from storage and pass it to the AppleScript action as a list in the input variable. That AppleScript action extracts the values from the list, concatenates them into a path string, and the uses the POSIX File command to turn that into a file reference. The fourth action stores the file reference in the outputFolder variable.
Note that the fifth action ignores the input from the fourth action. Instead, it recovers the original file specifier (that you will have stored somewhere earlier in the workflow, then sends the file specifier to the Move Finder Items actions, which uses the value stored in the outputFolder variable as its destination.
I've simplified the process and found a way with AppleScript:
on run {input, parameters}
set theFile to input as text
set yearName to ((characters 34 thru -1 of theFile) as string) --trim first 35
set yearName to ((characters 1 thru -22 of yearName) as string) --trim last 23
set monthName to ((characters 39 thru -1 of theFile) as string)
set monthName to ((characters 1 thru -19 of monthName) as string)
set destinationFolder to ("Macboot :Travail en cours:Google Drive:Company:Comptabilité:" & yearName & ":" & monthName & ":Compte Transferwise 1:Relevé PDF + fichier CSV:" as text)
tell application "Finder"
activate
move theFile to destinationFolder -- use "copy source_file to folder (target_folder as alias)" to copy the files
end tell
set result to {yearName, monthName, theFile, destinationFolder}
return result
end run
I have two workflows and I need to pass a value generated in one workflow to another workflow.
In my first workflow, I have an AppleScript which returns a number I want to put into a second workflow which I call from the first workflow like so:
My second workflow (Create Class in iStudiez) has a variable 'Class Number' which I want to change when I call it from my first workflow with the return value of the AppleScript pictured above.
Since you are using Automator and AppleScript in Automator, and you have not posted any actual code, it's difficult to give you an exact answer of what you're looking for.
There may be an easier solution but the solution I came up with was to create one script which will save a variable into a new script file (which will automatically be created on your desktop with the name of “Stored_Variable.scpt”. The second script loads the value of the variable stored in the “Stored_Variable.scpt” file.
Simply paste the code from this first script, directly into the code which contains the variable you want to copy. Be sure to paste the code after the code which sets the value of the variable you want copied.
-- Comment Out This Next Line Before
-- Placing This Code Into Your Script
-- Which Contains The Variable You Want Copied
set originalVariable to (path to desktop) -- Testing Purposes Only
-- Replace "originalVariable" with the
-- Name Of Your Actual Variable You Want To Pass
-- To The Next Script
set saveThisVariable to originalVariable
storeTheVariable()
-- The Following Code Belongs At The Very Bottom Of Your Script
on storeTheVariable()
set storedVariabeFileLocation to (path to desktop as text) & "Stored_Variable.scpt"
----------------------
script theVariable
set saveThisVariable to saveThisVariable
end script
----------------------
store script theVariable in ¬
file storedVariabeFileLocation with replacing
end storeTheVariable
Place this is second code inside the code of your AppleScript in which you are trying to retrieve the variable stored from the first AppleScript code
-- Gets The Variable Which Was Previously Stored
-- From The Other Applescript And Stores It In A
-- New Variable... getVariableNow
set getVariableNow to run loadTheVariable
-- -----------------------------------
-- Place Whatever Commands Here, That You Will Be Using
-- The New Variable... getVariableNow with
-- -----------------------------------
-- The Following Code Belongs At The Very Bottom Of Your Script
script loadTheVariable
property storedVariabeFileLocation : (path to desktop as text) & "Stored_Variable.scpt"
property theRetrievedVariable : missing value
on getStoredVariable()
set theScript to load script file storedVariabeFileLocation
set theRetrievedVariable to saveThisVariable of (theVariable of theScript)
end getStoredVariable
set theRetrievedVariable to loadTheVariable's getStoredVariable()
end script
So, I'm trying to build a very small shell script that grabs the currently playing Spotify song and returns the lyrics of the song in the terminal.
What works
The applescript returns/echos the track name to the terminal
What I need help with
I can't seem to retrieve values of theArtist and theName from the applescript, to use in the curl command below.
Any tips on how to make this work? :)
echo "tell application \"Spotify\"
set theTrack to current track
set theArtist to artist of theTrack
set theName to name of theTrack
end tell" | osascript
song=`curl -s "http://makeitpersonal.co/lyrics?artist=$theArtist&title=$theName"`
echo -e "$theArtist - $theName\n$song"
Try:
# Get information from Spotify via AppleScript and store it in shell variables:
IFS='|' read -r theArtist theName <<<"$(osascript <<<'tell application "Spotify"
set theTrack to current track
set theArtist to artist of theTrack
set theName to name of theTrack
return theArtist & "|" & theName
end tell')"
# Create *encoded* versions of the artist and track name for inclusion in a URL:
theArtistEnc=$(perl -MURI::Escape -ne 'print uri_escape($_)' <<<"$theArtist")
theNameEnc=$(perl -MURI::Escape -ne 'print uri_escape($_)' <<<"$theName")
# Retrieve lyrics via `curl`:
lyrics=$(curl -s "http://makeitpersonal.co/lyrics?artist=$theArtistEnc&title=$theNameEnc")
# Output combined result:
echo -e "$theArtist - $theName\n$lyrics"
AppleScript implicitly returns the result of the last statement; thus, in order to return multiple items of information, build up a string to return with an explicit return statement .
You then need to parse the output string into its components using read (here I've chosen | as a separator, because it's unlikely to be contained in artist names or song titles) and assign them to shell variables (AppleScript is an entirely separate world, and its variables are not accessible to the shell - the information must be passed via output string).
For the curl command to work, the information you splice into the URL must be properly URL-encoded (e.g., Pink Floyd must be encoded as Pink%20Floyd), which is what the perl commands do.
I have a folder containing about 5000 files with names like:
Invoice 10.1 (2012) (Digital) (4-Attachments).pdf
Carbon Copy - Invoice No 02 (2010) (2 Copies) (Filed).pdf
01.Reciept #04 (Scanned-Copy).doc
I want to rename these files by removing everything from the first bracket onwards, so they look like this:
Invoice 10.1.pdf
Carbon Copy - Invoice No 02.pdf
01.Reciept #04.doc
I have found lots of scripts that will remove the last x letters, but nothing that will crop from a particular character.
Ideally I would like to use Automator, but I'm guess this might too complex for it. Any ideas?
Try:
set xxx to (choose folder)
tell application "Finder"
set yyy to every paragraph of (do shell script "ls " & POSIX path of xxx)
repeat with i from 1 to count of yyy
set theName to item i of yyy
set name of (file theName of xxx) to (do shell script "echo " & quoted form of theName & " | sed s'/ (.*)//'")
end repeat
end tell
The code posted by #adayzone will work, but there is no need to use sed for this – plain AppleScript will do, using offset:
set fullString to "Invoice 10.1 (2012) (Digital) (4-Attachments).pdf"
set trimmedString to text 1 thru ((offset of "(" in fullString) - 1) of fullString
-- trim trailing spaces
repeat while trimmedString ends with " "
set trimmedString to text 1 thru -2 of trimmedString
end repeat
this returns “Invoice 10.1". To split the file name into the name and extension, and re-add the extension, you can use System Events’ Disk-File-Folder suite, which will provide the handy name extension property you can store and re-add after trimming the name.
Assuming you use some Automator action to get the files to be processed, the full processing workflow would be to add an AppleScript action after the file selection part with the following code:
repeat with theFile in (input as list)
tell application "System Events"
set theFileAsDiskItem to disk item ((theFile as alias) as text)
set theFileExtension to name extension of theFileAsDiskItem
set fullString to name of theFileAsDiskItem
-- <insert code shown above here>
set name of theFileAsDiskItem to trimmedString & "." & theFileExtension
end tell
end repeat
If you want your Automator workflow to process the files any further, you will also have to create a list of aliases to the renamed files and return that from the AppleScript action (instead of input, which, of course, is not valid anymore).
I made this Applescript script to create symbolic links.
Appart from POSIX path of, how can I get the file name, without the path, of the dropped file?
on open filelist
repeat with i in filelist
do shell script "ln -s " & POSIX path of i & " /Users/me/Desktop/symlink"
end repeat
end open
PS: I know this expects many files to be dropped and tries to create many links with the same name, which gives an error. Actually I copied this example from a website and as I don't know almost anything about Applescript, I don't know how to do this for a single file, help on that would be appreciated too.
I'm not sure what precisely you're trying to do, but I have a guess. Is the idea that you want to take every file dropped on the script and create a symbolic link to each one on the Desktop? So if I drop ~/look/at/me and ~/an/example, you'll have ~/Desktop/me and ~/Desktop/example? If that's what you want, then you're in luck: ln -s <file1> <file2> ... <directory> does exactly that. (Edit: Although you have to watch out for the two-argument case.) Thus, your code could look like this:
-- EDITED: Added the conditional setting of `dest` to prevent errors in the
-- two-arguments-to-ln case (see my comment).
on quoted(f)
return quoted form of POSIX path of f
end quoted
on open filelist
if filelist is {} then return
set dest to missing value
if (count of filelist) is 1 then
tell application "System Events" to set n to the name of item 1 of filelist
set dest to (path to desktop as string) & n
else
set dest to path to desktop
end if
set cmd to "ln -s"
repeat with f in filelist & dest
set cmd to cmd & " " & quoted(f)
end repeat
do shell script cmd
end open
Note the use of quoted form of; it wraps its argument in single quotes so executing in in the shell won't do anything funny.
If you want to get at the name of the file for another reason, you don't need to call out to the Finder; you can use System Events instead:
tell application "System Events" to get name of myAlias
will return the name of the file stored in myAlias.
Edit: If you want to do something to a single file, it's pretty easy. Instead of using repeat to iterate over every file, just perform the same action on the first file, accessed by item 1 of theList. So in this case, you might want something like this:
-- EDITED: Fixed the "linking a directory" case (see my comment).
on quoted(f)
return quoted form of POSIX path of f
end quoted
on open filelist
if filelist is {} then return
set f to item 1 of filelist
tell application "System Events" to set n to the name of f
do shell script "ln -s " & ¬
quoted(f) & " " & quoted((path to desktop as string) & n)
end open
It's pretty much the same, but we grab the first item in filelist and ignore the rest. Additionally, at the end, we display a dialog containing the name of the symlink, so the user knows what just happened.
As an example, you can work with the Finder instead of a shell script to get the name of a single file that is dropped on the script that is saved as an application. If you don't need the display dialog, you can remove it, but you have the file name as a variable to work with:
on open the_files
repeat with i from 1 to the count of the_files
tell application "Finder"
set myFileName to name of (item i of the_files)
end tell
display dialog "The file's name is " & myFileName
end repeat
end open