Is it possible to write an AppleScript that will execute a command when the timestamp on a named file changes?
I’m working on an automation process with a Linux user and he has put something like this together for Linux and I’m wondering if the same can be done on a Mac.
The idea is to select a file, run a command on the file and then “listen” for a change in timestamp on that file. If the timestamp changes, then the command is run again against the named file, if it doesn’t change, the command is not re-run.
The main problem I see here is how would you then exit such a script/program once you were through with it?
Is it possible to write a script that you then export as an app, but which does not reply on a visible dialog to close (i.e. could it be closed at some point via cmd+Q?).
I’ve found I can get the file timestamp using the following bash command:
stat file.docx | cut -d " " -f12
12:48:12
But when I try to convert this to AS, my syntax must be letting me down somewhere:
set default_folder_Location to (path to home folder as text) & "01 Translations:03 Projects:"
set theFile to (choose file with prompt "Choose file:" default location alias default_folder_Location)
set oldTimestamp to "stat " & quoted form of POSIX path of theFile & " | cut -d \" \" -f12"
do shell script "echo " & oldTimestamp
The result I get is just “”.
I thought the problem might be POSIX-related, so I then tried this:
set default_folder_Location to (path to home folder as text) & "01 Translations:03 Projects:"
set theFile to (choose file with prompt "Choose file:" default location alias default_folder_Location)
set theFilePOSIX to the quoted form of POSIX path of theFile
set oldTimestamp to "stat " & theFilePOSIX & " | cut -d \" \" -f12"
do shell script "echo " & oldTimestamp
If the script itself runs without an error (i.e. it doesn’t refuse to run because it sees an error in syntax), can anyone advise how I can troubleshoot this?
--set default_folder_Location to (path to home folder as text) & "01 Translations:03 Projects:"
set theFile to (choose file with prompt "Choose file:")
set oldTimestamp to "stat " & quoted form of POSIX path of theFile & " | cut -d \" \" -f12"
set x to do shell script oldTimestamp
The only real change is that I’m not "echo"ing the shell script!
Before I saw your replies, I “fixed” the problem this way:
set default_folder_Location to (path to home folder as text) & "01 Translations:03 Projects:"
set htmlFile to (choose file with prompt "File to convert:" default location alias default_folder_Location)
set htmlFilePOSIX to the quoted form of POSIX path of htmlFile
set oldTimestamp to (do shell script "stat " & htmlFilePOSIX & " | " & "cut -d \" \" -f12")
Is there a difference in how this is achieved (one better than the other)?
I’m almost there, but am unsure how to finish this.
What I’m trying to do is launch this script, select a docx file, check its time stamp, convert it to HTML and then, if the time stamp of the original docx file changes (has been updated), the conversion process is run again to created an updated HTML file. This would then set the newTimestamp as the oldTimestamp, waiting to see if there is a further update.
Here is what I have so far:
-- Script to update OmegaT projects for previewing
-- in the Opera browser. Written with the generous
-- advice of McUsr and StefanK at Macscripter.net
-- extend the default 2 minute timeout
with timeout of (30 * 60) seconds
-- set path relative to home folder
set default_folder_Location to (path to home folder as text) & "01 Translations:03 Projects:"
set htmlFile to (choose file with prompt "File to convert:" default location alias default_folder_Location)
set htmlFilePOSIX to the quoted form of POSIX path of htmlFile
set oldTimestamp to (do shell script "stat " & htmlFilePOSIX & " | " & "cut -d \" \" -f12")
tell application "Finder"
reveal htmlFile
do shell script "textutil -convert html " & htmlFilePOSIX
tell application "System Events"
tell application "Opera" to activate
end tell
end tell
repeat
set newTimestamp to (do shell script "stat " & htmlFilePOSIX & " | " & "cut -d \" \" -f12")
if newTimestamp does not equal oldTimestamp then
do shell script "textutil -convert html " & htmlFilePOSIX
set newTimestampt to oldTimestamp
tell application "System Events"
tell application "Opera" to activate
end tell
end repeat
-- end timeout
end timeout
It complains, however, about the “end repeat” in the repeat loop, saying “Expected end of line etc., but found repeat”
Surely I have to terminate the repeat, right? Otherwise, how will it know where the repeat starts and stops?
Thanks, Stefan. School boy error on my part. Was too concerned about the other aspects.
It works now, but strangely, it won’t let Opera go. Once Opera moves to the foreground, it’s like it loops over that and I can change focus to anything else. If I cmd+q out of Opera, it just launches it again.
I think I must have made a syntax error when making the newTimestamp the oldTimestamp. Do you know what I mean?
I assign a starting time stamp and then check for a new timestamp. If the “old” and the “new” aren’t the same, the conversion runs again and Opera comes to the fore. The “new” stamp then becomes the “old” so a future comparison can be made.
Thanks, Stefan. Sorry, I’ve become a bit snowblind.
I fixed that and changed the variables as you indicated, but it’s still not letting me get away from Opera. If I quit out of Opera, it relaunches and after doing this twice I get the following error:
error “Opera got an error: Connection is invalid.” number -609
I don’t know what this means. Does it make sense to you?
launchd can observe folders for file system changes (similar to folder actions).
A file system change occurs for example when a time stamp of a file changes or a file is added or removed.
The notification can trigger a script to handle the event.
Unlike the polling solution notifications don’t consume CPU power.
I see one problem with this option (please correct me if I’m wrong - which I probably am):
In the article (http://macscripter.net/viewtopic.php?id=24748) it says that launchd is watching the path (in the case of the article) /Volumes/, which is very high level and static. In my case, I will be working at a low level (project level) and as such, the path will be very long and dynamic.
The highest level that won’t change would be /Users/bowjest/01 Translations/03 Projects, but this is then subdivided by folders for customers, so have some dozen or so folders, each with their own data and project files.
If anything changes at the higher level, won’t this cause launchd to fire and try to carry out the contents of my script at the highest level (/Users/bowjest/01 Translations/03 Projects), thus trying to access all the data contained therein?
With my script as it stands, the user would only ever select one file for the duration of the session.
If, for instance, I were working on a project (proofing corrections) for 20-30 mins or even an hour or more, the polling would only take place while I was working on that project.
This is why I initially used the button solution below:
-- extend the default 2 minute timeout
with timeout of (30 * 60) seconds
-- set path relative to home folder
set default_folder_Location to (path to home folder as text) & "01 Translations:03 Projects:"
set htmlFile to (choose file with prompt "File to convert:" default location alias default_folder_Location)
tell application "Finder"
reveal htmlFile
do shell script "textutil -convert html " & quoted form of POSIX path of htmlFile
tell application "System Events"
tell application "Opera" to activate
end tell
end tell
repeat
display dialog "Update HTML File" buttons {"Cancel", "Update"} default button "Update"
do shell script "textutil -convert html " & quoted form of POSIX path of htmlFile
tell application "System Events"
tell application "Opera" to activate
end tell
end repeat
-- end timeout
end timeout
But this requires the user to toggle to the app and hit return or click the update button.
I’ll see if the tcl/tk solution my colleague has written for Linux can be used with Macs as well without a lot of system overhead.
Thanks, Stefan. It’s always a learning experience when you lend a hand.
I’ve got the preview.tcl script to work by changing some parameters and running this:
wish preview.tcl target.docx
I’ve tried to update my script accordingly, but it fails to run correctly. Here is the script:
-- extend the default 2 minute timeout
with timeout of (30 * 60) seconds
-- set path relative to home folder
set default_folder_Location to (path to home folder as text) & "01 Translations:03 Projects:"
set htmlFile to (choose file with prompt "File to convert:" default location alias default_folder_Location)
set htmlFilePOSIX to the quoted form of POSIX path of htmlFile
set previewTCL to (path to home folder as text) & "Library:Preferences:OmegaT:script:preview.tcl"
tell application "Finder"
reveal htmlFile
do shell script "textutil -convert html " & htmlFilePOSIX
tell application "System Events"
tell application "Opera" to activate
end tell
end tell
repeat
display dialog "Update HTML File" buttons {"Cancel", "Update"} default button "Update"
do shell script "wish " & previewTCL & htmlFilePOSIX
tell application "System Events"
tell application "Opera" to activate
end tell
end repeat
-- end timeout
end timeout
The error I get is:
error “The command exited with a non-zero status.” number 1
Can anyone advise what the problem is? Does it need to print to console or something to work and that’s why it’s failing in script?
I’ve gone back and assigned a POSIX path to the tcl script:
set previewTCL to (path to home folder as text) & “Library:Preferences:OmegaT:script:preview.tcl”
set previewTCLPOSIX to the quoted form of POSIX path of previewTCL
and tried to put a space after previewTCLPOSIX and the selected file, but it still fails: