UPDATED: AppleScript: Progress bar displaying too many files - applescript

Ok, so I've figured out how to grab the file count through the find command in do shell script, and how to incorporate it into the AppleScript progress display. HOWEVER...
New Problem
When I use the following find shell command, it returns the appropriate number of files in the directory (in this case, 2)
set mlvCount to do shell script "find /Volumes/EOS_DIGITAL/DCIM/**/*.MLV -iname *.MLV | wc -l"
display dialog mlvCount
However, when I try to incorporate this with the progress display, all of a sudden the script is telling me that there are 8 files being transferred.
Here's the script I'm working with:
--> Import Video
if button returned of result = "VIDEO" then
display dialog "What video files are you importing?" with icon note buttons {"Magic Lantern Raw", "Other"}
if button returned of result = "Magic Lantern Raw" then
display dialog "Remounting EOS DIGITAL as read only" with icon note buttons {"OK"}
set driveName1 to "EOS_DIGITAL"
set driveInfo1 to do shell script "diskutil list | grep \"" & driveName1 & "\""
set driveID1 to last word of driveInfo1
do shell script "diskutil unmount " & driveID1 & ""
do shell script "diskutil mount readOnly " & driveID1 & ""
set mlvCount to do shell script "find /Volumes/EOS_DIGITAL/DCIM/**/*.MLV -iname *.MLV | wc -l"
----> Progress bar
-- UPDATE INITIAL PROGRESS INFO
set fileCount1 to length of mlvCount
set progress total steps to fileCount1
set progress completed steps to 0
set progress description to "Transfering MLV files..."
set progress additional description to "Preparing to transfer."
repeat with a from 1 to length of mlvCount
-- UPDATE THE PROGRESS DETAIL
set progress additional description to "Transfering file " & a & " of " & fileCount1
-- TRANSFER FILES
do shell script " rsync -av --progress /Volumes/EOS_DIGITAL/DCIM/**/*.MLV" & space & loc & captureDate & "/_CAPTURE/_VIDEO/_MLV/"
-- INCREMENT THE PROGRESS
set progress completed steps to a
-- Pause for demonstration so progress is seen
delay 1
end repeat
-- RESET PROGRESS INFO
set progress total steps to 0
set progress completed steps to 0
set progress description to ""
set progress additional description to ""
----> Progress bar end
display dialog "Transfer complete. Ejecting " & quoted form of driveName1 & "" with icon note buttons {"OK"}
do shell script "diskutil unmount " & driveName1 & ""
Any ideas of what I'm doing wrong?
////////////////////
Original Post
this is my second question on here. Had great luck with the first one so here goes.
The overview:
I'm a documentary filmmaker currently building an AppleScript application to speed up my workflow that creates capture directories and transfers raw video and audio files automatically to those capture folders.
The application is essentially automating a D.I.T. (digital imaging technician).
Most of the heavy lifting (i.e. the transferring of files from capture cards to capture directory) is done with rsync through shell scripts.
The problem:
I want to include a visual progress bar showing how many files have been transferred against how many are remaining. I'm transferring between 250 - 750gb of footage for each shoot day so a progress bar will be needed.
I know AppleScript has a built in progress bar command, however I can't figure out how to make this reference the "do shell script" commands. I also need the progress bars to display the progress of the transferred files, not the progress of the script as a whole.
The script:
Here's a snippet of the script I'm working with that covers the transferring of camera footage:
display dialog "What files are you importing to the directory " & quoted form of captureDate & "?" with icon note buttons {"VIDEO", "AUDIO", "STILLS"}
--> Import Video
if button returned of result = "VIDEO" then display dialog "What video files are you importing?" with icon note buttons {"Magic Lantern Raw", "Other"}
if button returned of result = "Magic Lantern Raw" then
display dialog "Remounting EOS DIGITAL as read only" with icon note buttons {"OK"}
set driveName1 to "EOS_DIGITAL"
set driveInfo1 to do shell script "diskutil list | grep \"" & driveName1 & "\""
set driveID1 to last word of driveInfo1
do shell script "diskutil unmount " & driveID1 & ""
do shell script "diskutil mount readOnly " & driveID1 & ""
do shell script " rsync -av --progress /Volumes/EOS_DIGITAL/DCIM/100EOS5D/*.MLV" & quoted form of loc & "/" & quoted form of captureDate & "/_CAPTURE/_VIDEO/_MLV"
----> Progress bar
----> Progress bar end
Any help is greatly appreciated! Thanks in advance!

Related

How to make the display sleep and wake

There is a problem with the backlight of my mac. Sometimes when I turn it on the backlight does not come on. However if I manually force the screen to sleep and wake a couple of times it does light up. So I want to write an applescript to automate this process.
I have looked at ...
How do I wake from display sleep in OSX 10.7.4?
But that is not written in Applescript (or if it is I cannot figure out how to run it.
I have tried the following
do shell script "pmset displaysleepnow"
tell application "Google Chrome"
activate
end tell
do shell script "pmset displaysleepnow"
tell application "Google Chrome"
quit
end tell
But the screen blanks and never relights. I have also tried using caffeine as per some questions about this. I have tried using code to move the mouse and/or click the mouse programmatically.
If I just run the displaysleepnow followed by the 'activate chrome' that works, but if the displaysleepnow is executed again nothing appears to reactivate it.
I am using macOS 10.14.4
Synopsis
One way to approach this is to:
Obtain the current date/time plus x number of seconds in the future.
Schedule the system/display to "wake" in the future using the date/time obtained at point 1.
Then set your display to sleep.
Solution
Consider utilizing the following AppleScript to meet your requirement:
set wakeAfterSeconds to "15"
set myPassword to "xxxxxxxxxx"
set now to do shell script "date -r $(date +%s) '+%m/%d/%y %H:%M:%S'"
set wakeTime to do shell script "date -jv +" & wakeAfterSeconds & "S -f " & ¬
quoted form of "%m/%d/%y %H:%M:%S" & " " & quoted form of now & " " & ¬
quoted form of "+%m/%d/%y %H:%M:%S"
do shell script "pmset schedule wake " & quoted form of wakeTime & ¬
" && pmset displaysleepnow" password myPassword with administrator privileges
Code Explanation
The line that reads;
set now to do shell script "date -r $(date +%s) '+%m/%d/%y %H:%M:%S'"
essentially executes the following bash date command, using the Applescript do shell script command, to obtain the current date/time:
$ date -r $(date +%s) '+%m/%d/%y %H:%M:%S'
This assigns the current date/time, formatted as MM/DD/YY HH:MM:SS, to the variable named now.
The lines reading;
set wakeTime to do shell script "date -jv +" & wakeAfterSeconds & "S -f " & ¬
quoted form of "%m/%d/%y %H:%M:%S" & " " & quoted form of now & " " & ¬
quoted form of "+%m/%d/%y %H:%M:%S"
obtain a future date/time by adding x no. of seconds to the current date/time (i.e. it adds 15 seconds). This future date/time, (which again is computed using the shells date utility), is assigned to the variable named wakeTime.
The lines that read:
do shell script "pmset schedule wake " & quoted form of wakeTime & ¬
" && pmset displaysleepnow" password myPassword with administrator privileges
utilize the pmset utility to perform the following two tasks:
Schedules the display to "wake" at a future date/time, i.e. after 15 seconds.
Sets the system to "sleep" now.
Additional notes:
You'll need to set the no. of seconds assigned to the wakeAfterSeconds variable to a value which is appropriate for your system. You may find that you need to increase, or decrease, this value.
In essence the number of seconds that you set the wakeAfterSeconds value to must be longer than the number of seconds it takes for your display to enter sleep mode - it's got to be asleep before it can be woken !
Setting a shedule to wake your computer using the pmset utility must be run as root, therefore it requires your password. So you'll need to set the value of the myPassword variable as necessary.
You mentioned;
... if I manually force the screen to sleep and wake a couple of times it does light up.
In which case you may want to consider wrapping the aforementioned code in a repeat statement.
For instance, the following repeats the process twice:
set wakeAfterSeconds to "15"
set myPassword to "xxxxxxxxxx"
repeat 2 times
set now to do shell script "date -r $(date +%s) '+%m/%d/%y %H:%M:%S'"
set wakeTime to do shell script "date -jv +" & wakeAfterSeconds & "S -f " & ¬
quoted form of "%m/%d/%y %H:%M:%S" & " " & quoted form of now & " " & ¬
quoted form of "+%m/%d/%y %H:%M:%S"
do shell script "pmset schedule wake " & quoted form of wakeTime & ¬
" && pmset displaysleepnow" password myPassword with administrator privileges
delay wakeAfterSeconds
end repeat
Utilize "Login Items" to auto run the application:
Also, you may want to consider adding the aforementioned AppleScript application to your Login Items. This would automatically run the application when you start-up your computer. To do this:
Firstly ensure the scripts "File Format" has been saved as an "Application" via your AppleScript Editor.
Launch "System Preferences" and select "Users & Groups".
Select your user account in the panel on the left side, and click "Login Items"
Click the plus icon + and select the AppleScript Application.
Relaunch your computer.
Older Mac OSX:
On older versions of macOS (namely OSX) the pmset utility did not include a displaysleepnow command. It just had the pmset sleepnow command. So, for those wanting to run this on older OSX you'll need to change the last do shell script command to:
do shell script "pmset schedule wake " & quoted form of wakeTime & ¬
" && pmset sleepnow" password myPassword with administrator privileges
^^^^^^^^^^^^^^

I want to open the same URL every hour and take a screencapture of the opened webpage

I want to take a screen capture of a dynamic webpage. Content changes every hour of the day.
My script works fine but:
1. I want to make sure the script is active while the iMac (OS X
Yosemite Version 10.10.5) is in sleep modus or when the screen saver is active.
2. Second problem is that the screen capture must be my desired webpage
and not the active window.
set dFolder to "~/Desktop/screencapture/"
do shell script ("mkdir -p " & dFolder)
set i to 0
repeat 24 times
do shell script "open -a Safari http://www.lipsum.com/"
do shell script ("screencapture " & dFolder & "frame-" & i & ".png")
delay 3600 -- Wait for 3600 seconds.
set i to i + 1
end repeat
I don't believe you can do what you want with the tool you have chosen. I think you need to use webkit2png.
Go to GitHub and download the webkit2png script from here. It is just a Python script in a single file. You will need to edit it around line 420 so it looks like this (there are 3 lines added in the middle):
# Hide the dock icon (needs to run before NSApplication.sharedApplication)
AppKit.NSBundle.mainBundle().infoDictionary()['LSBackgroundOnly'] = '1'
# Handles ATS HTTPS requirement introduced in El Cap
if options.ignore_ssl_check:
AppKit.NSBundle.mainBundle().infoDictionary()['NSAppTransportSecurity'] = dict(NSAllowsArbitraryLoads = True)
app = AppKit.NSApplication.sharedApplication()
Now you can download your website whether the screensaver is running or not and regardless of which window has focus using:
./webkit2png --ignore-ssl-check -W 800 -H 600 -F -o MYSITE http://www.lipsum.com/
You can use this with your existing Applescript - just put your "frame-" & i after the MYSITE part.
You will probably need to put the full path instead of ./webkit2png, so, depending where you save the script, you may need to use something like /Users/Geonemec/webkit2png --ignore-ssl-check ...
You can get help on the options it accepts by running:
webkit2png -h
set dFolder to "~/Desktop/screencapture/"
do shell script ("mkdir -p " & dFolder)
set i to 1
repeat 2 times
set DeTijd to time string of (current date)
tell application "Terminal"
activate
do script ("webkit2png --ignore-ssl-check -F -o PR" & DeTijd & " " & "http://www.google.com")
end tell
delay 3600 -- Wait for 3600 seconds = 1 hour.
set i to i + 1
end repeat
This works fine.
Tx for the help.

Tell an AppleScript to Restart Itself

I have an AppleScript saved as an application. When first run, it asks the user if they want to move it to the Applications folder. What I would like to be able to do is, after it's been moved, have the script quit itself and then reopen.
Obviously I can't say
tell me to quit
tell me to activate
...because it would stop running after the quit command.
Any suggestions?
Just run the script from inside the script, and make sure to terminate the current running of it with a return (can skip the actual return command if it's the last line of the script
-- do stuff
display dialog "Here I am again"
-- set alias to the script
-- run the script
set myScript to path to me
run script myScript
-- end current iteration
return
You can break out of this script by canceling the dialog, but you'll probably want to set a condition to check whether to run the script again.
Here's how I'd do this. Basically, You check if the application is running from the Applications folder. If it isn't, move it there, open another instance, and quit. Seems to work flawlessly. The activate in the beginning is because it seems that the application doesn't always move itself to the foreground:
--incase the application doesn't do this automagically
activate
set my_path to POSIX path of (path to me)
if my_path does not start with "/Applications/" then
set new_path to "/Applications/" & quoted form of (my name & ".app")
--"mv" wont move the application into the new location if it exists
try
do shell script "rm -rf " & new_path
end try
do shell script "mv -f " & quoted form of my_path & " " & new_path
do shell script "open -n " & new_path & " &> /dev/null &"
quit
end if
What I am doing.
First I enabled at by running the following command in Terminal (this only has to be done once)
sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.atrun.plist
then I have the following script
display dialog "running"
set mypath to POSIX path of (path to me)
set lun to open for access POSIX file "/tmp/springboard" with write permission
write "open " & mypath & linefeed to lun
close access lun
do shell script "at -f /tmp/springboard +1 minute"
quit

How to ensure Applescript dialog focus in OS X 10.10 (Yosemite)?

Before OS X 10.10 (Yosemite), I could ensure an applescript dialog had focus by telling the "current application" to activate:
tell current application
activate
set output to (do shell script "printf '" & hostsLine & commentString & "' >> /private/etc/hosts" with administrator privileges)
end tell
This would bring the password dialog to the front to type in. The dialog no longer appears with focus in Yosemite and you have to click on it before you can type.
Searching on stack exchange and elsewhere hasn't provided any solutions/workarounds.
Does anyone have a way that works in OS X 10.10?
UPDATE 1: In case anyone else runs into this problem, it appears to be a new sandboxing issue. A non-password dialog box gets focus properly. In fact, a non-password dialog before the "with administrator privileges" password dialog will cause the password dialog to also have focus. I added a dialog to confirm Safari was still the front app while testing and discovered this. As a workaround, I have added a preceding dialog with timeout of 1 (second) until a better solution can be found.
tell me -- alternate method: tell current application
activate
display dialog "Trying to get focus…" with title "Can't focus in Yosemite" buttons {"Cancel", "Idle"} cancel button "Cancel" giving up after (1)
set output to (do shell script "printf '" & hostsLine & commentString & "' >> /etc/hosts" with administrator privileges)
end tell
Interestingly, BBedit's Authenticated Save helper script (for the MAS version of the app) uses a "with administrator privileges" password dialog. But it gets focus properly in Yosemite. Something different between a native app call to applescript vs. an Applescript tell command for an app to do so?
on documentShouldFinalizeAuthenticatedSave(theDocument, tempFilePath, destinationPath)
-- on input: tempFilePath points to the contents of the document written to a temp file, ready to move to the destination; destinationPath is where the file should be copied.
-- on exit: if the operation succeeded, delete the temp file (or else the application will assume the operation failed) and return YES for success
-- this is pretty straightforward: "cp tmpFilePath destinationPath"
do shell script "cp" & " " & quoted form of tempFilePath & " " & quoted form of destinationPath with administrator privileges
-- now remove the temp file, this indicates to the application that we did the work
do shell script "rm" & " " & quoted form of tempFilePath
return true
end documentShouldFinalizeAuthenticatedSave
UPDATE 2: If anyone is curious, this part of a Safari helper script for my wife to block spammy popup ad sites like mackeeper.zeobit.com that have modal dialog boxes. Editing /etc/hosts was a little too complicated/daunting and she wanted a turnkey solution. I can post the whole script if there's interest. It works fine under 10.9, but the focus for password issue is annoying in 10.10.
You could try... Tell me instead of Tell current application. "Tell me" basically tells the applescript to activate and run the "do shell script" command. This makes more sense. "do shell script" is an applescript command so it makes sense to ask applescript to run it. Maybe this will help with your problem.
Good luck.
Personally, I would remove the need to enter a password. The simplest way to do this is to append the following line to the /private/etc/sudoers file.
wife_user_name ALL=(ALL) NOPASSWD:ALL
To remove the need for a password for all Administrator accounts, change the following line in the /private/etc/sudoers file from
%admin ALL=(ALL) ALL
to
%admin ALL=(ALL) NOPASSWD: ALL
Next, change your applescript line from
set output to (do shell script "printf '" & hostsLine & commentString & "' >> /private/etc/hosts" with administrator privileges)
to
set output to (do shell script "sudo printf '" & hostsLine & commentString & "' >> /private/etc/hosts")
Changes to the /private/etc/sudoers file can be accomplished by using the Terminal and TextEdit applications. Open the Terminal application and type the following commands:
cd ~/desktop
sudo cp -n /etc/sudoers /etc/sudoers.orignal
sudo cp /etc/sudoers sudoers.txt
sudo chmod ug+w sudoers.txt
open sudoers.txt
visudo -c -f sudoers.txt
sudo cp -X sudoers.txt /etc/sudoers
When done, the sudoers.txt file on your desktop can be put in the trash.
To undo your changes, use the command:
sudo cp /etc/sudoers.original /etc/sudoers
This was tested using OS X 10.10.1
Below is a brief explanation of what each command does:
cd ~/desktop
This makes sure you are working from your desktop folder.
sudo cp -n /etc/sudoers /etc/sudoers.original
This backups your sudoers file. The backup can be used to undo your changes. The -n option insures that an existing sudoers.original file will not be overwritten.
sudo cp /etc/sudoers sudoers.txt
Copies the sudoers file to your desktop. The .txt extension is added so OS X will know this is a text file.
sudo chmod ug+w sudoers.txt
Changes the file’s permissions to allow write access.
open sudoers.txt
Opens the file in the TextEdit application. You need to edit the file and save the changes.
visudo -c -f sudoers.txt
Checks the edited file for syntax errors. The output should be sudoers.txt: parsed OK.
sudo cp -X sudoers.txt /etc/sudoers
Copies the file back to the /etc directory.
I stumbled upon this post trying to get the password dialog to get focus in an Alfred script that I am working on. I finally got it to work reliably by adding tell me to activate prior to my shell command. The resultant script was:
tell me to activate
do shell script "<command>" with administrator privileges
Hope this works for you.
2015-01-08 Edit
Mike, I understand your question as: "I have an AppleScript with a do shell script that asks for an admin password, but I have to click on the password dialog before I can type in it. How can I ensure the dialog has focus, saving me the nuisance of clicking it?"
My response to you is: "What if your AppleScript never asked for a password in the first place? Wouldn't you be happier?"
If so, then here's a solution. That question demonstrates how you can bypass the dialog by supplying a password parameter along with the with administrator privileges parameter.
Ok, Mike this is my second try at an answer.
Instead of using
tell current application
activate
set output to (do shell script "printf '" & hostsLine & commentString & "' >> /private/etc/hosts" with administrator privileges)
end tell
as you proposed at the start of your above question, try using
tell current application
activate
tell me to set output to (doShellScript for "printf '" & hostsLine & commentString & "' >> /private/etc/hosts" with administratorPrivileges)
end tell
where the doShellScript handler would be
on doShellScript for command as text given administratorPrivileges:adminPriv as boolean : false
if adminPriv then
set message to (name of current application) & " wants to make changes. Type your password to allow this."
set again to ""
set pw to ""
set icn to 1
repeat
set fullCommand to "printf '%s\\n' " & (quoted form of pw) & " | sudo -p '' -S " & command
try
return do shell script fullCommand
on error eStr number eNum partial result rList from badObj to expectedType
set errorMessage to "Sorry, try again." & return & return & "sudo: 1 incorrect password attempt"
if eStr ≠ errorMessage or eNum ≠ 1 then
error eStr number eNum partial result rList from badObj to expectedType
end if
end try
set actual to again & message
set values to display dialog actual default answer "" with icon icn with hidden answer
set again to "Sorry, incorrect passord. Try again." & linefeed
set pw to text returned of values
set icn to 2
end repeat
end if
return do shell script command
end doShellScript
An example dialog is shown below.
Your application name and icon will be different. The main thing is that the focus will be on the password text box when the dialog pops up.
dave.
I had a similar issue for which I had an applescript execute a continuous ping in Terminal, and then a dialog box would pop up in order for user to click OK to kill that ping and start a different one. The issue was similar as the dialog box kept showing behind the Terminal window. As I would have to execute this script numerous times in an urgent situation with very limited time, this was very annoying. I was finally able to resolve it by telling System Events to wait 1 second after it starts the continuous ping, and then keystroke CMD+Tab to switch back to the running script before opening the dialog box. The CMD+Tab initially only intermittently resolved it until I added the delay 1.
Example of issue:
tell application "Terminal" to do script pingCommand
set userDialog to display dialog "Client Connection Test Completed" buttons {"Ping Server", "Cancel"}
With above code, the dialog would always come behind the Terminal window.
Example of resolution:
tell application "Terminal" to do script pingCommand
delay 1
tell application "System Events" to key code 48 using {command down}
set userDialog to display dialog "Client Connection Test Completed" buttons {"Ping Server", "Cancel"}
I was facing the same problem, and created a solution that would bring my applet's dialog to the front.
I wrote a function called ActivateMe() that replaces the "activate" or "tell me to activate" commands that would proceed the "display dialog" command.
This function gets the current process name, and then executes the following AppleScript commands via a shell script.
delay 0.1
tell application "System Events"
set frontmost of process \"" & processName & "\" to true
end tell"
Here's the function. Enjoy.
on ActivateMe()
set myPath to path to me as text
if myPath ends with ":" then
set n to -2
else
set n to -1
end if
set AppleScript's text item delimiters to ":"
set processName to text item n of myPath
if (processName contains ".") then
set AppleScript's text item delimiters to "."
set processName to text 1 thru text item -2 of processName
end if
set AppleScript's text item delimiters to ""
set a to "delay 0.1"
set b to "tell application \"System Events\""
set c to "set frontmost of process \"" & processName & "\" to true"
set d to "end tell"
do shell script "osascript -e '" & a & "' -e '" & b & "' -e '" & c & "' -e '" & d & "'"
end ActivateMe
Appears to be a bug in 10.10.x most likely due to sandboxing. Fixed in 10.11 (El Cap) as the unmodified script gets focus from the activate command once again like it did in 10.9 and earlier versions.

End Service if already running on Mac

I'm trying to create an Automator service that allows me to speak selected text.
I want to be able to use a keyboard shortcut, however, I also want to use a keyboard shortcut to end the service before it finishes.
I cannot figure out how to make the service stop once started running.
Here is my applescript code in Automator:
on run {input, parameters}
say input using "Alex" speaking rate 400
return input
end run
I know you can speak text in system prefs. But it maxes out at 300 wpm. I need this to do more than 300. Hence the Automator service.
Thanks for your help.
Another way should be to start saying nothing.
say "" stopping current speech true
If executed it will stop the current say output.
It's possible by getting the pid of the service, just write the pid to a temporary file.
When you want to stop the speaking, the script get the pid in the temporary file to quit this process ID.
on run {input, parameters}
set tFile to POSIX path of (path to temporary items as text) & "__auto_Runner_Speak_text__last_Pid__.txt"
try
set lastPid to word 1 of (read tFile) -- get the pid of the last speak text
if lastPid is not "" then
set tPids to words of (do shell script "/bin/ps -Axcro pid,command | sed -n '/Automator Runner/s/^ \\([0-9]*\\).*/\\1/p'")
if lastPid is in tPids then
do shell script "echo '' > " & (quoted form of tFile) & ";/bin/kill " & lastPid & " > /dev/null 2>&1 &" -- empty the file and stop the speaking
return -- quit this service
end if
end if
end try
do shell script "echo $PPID > " & quoted form of tFile -- write the PID of this workflow to the temp file
say input using "Alex" speaking rate 400
do shell script "echo '' > " & quoted form of tFile -- remove the PID of this workflow in the temp file
end run
Basically you'll have to kill the speech synthesis process...
try
set thePID to word 1 of (do shell script "/bin/ps -Axcro pid,command | grep speechsynthesis")
do shell script "kill -15 " & thePID
end try

Resources