8 Replies Latest reply: Aug 10, 2009 7:04 AM by Pendal
Pendal Level 1 Level 1 (5 points)
i need to process a command through the terminal. for whatever reason i need to process this particular command using the do script command.

the do shell script command will not parse the command properly.

the only problem is that i need to wait until the shell command is finished before the rest of the script continues.

Any suggestions?

Thanks,
-P

Mac MINI, Mac OS X (10.5.6)
  • 1. Re: do script ... please wait
    Camelot Level 8 Level 8 (45,790 points)
    the do shell script command will not parse the command properly.


    Without seeing the command you're trying, it's impossible to tell why, but it's almost certainly an issue of escaping - certain characters (such as quotes, backslashes, etc.) need to be escaped in AppleScript so they're passed to the shell in the form it expects. Posting the command should make it easy to fix.

    the only problem is that i need to wait until the shell command is finished before the rest of the script continues.


    If you used do shell script and not Terminal.app, this would be the default. If you require Terminal.app for some reason then you have several options.

    One is to poll the terminal window, looking at the last line of the window content to see if it's a prompt (indicating the process has finished).
    Another approach is to capture the PID of the process and use that in another do shell script command that polls for that process. This might be tricky if you expect the process to continue processing in the terminal window since capturing the PID can be hit-or-miss.
  • 2. Re: do script ... please wait
    Noaks Level 1 Level 1 (35 points)
    The approach I've used successfully is to add the following immediately after the do script command in AppleScript:

    repeat
    tell application "Terminal" to set BI_ to busy of front window
    if BI_ is false then exit repeat
    end repeat
    end tell


    This stalls the AppleScript until the Terminal command is complete. There may be some downside to doing this, but none has surfaced so far.
  • 3. Re: do script ... please wait
    Camelot Level 8 Level 8 (45,790 points)
    Interesting approach, Noaks, and it should work.

    I'd just make one change, though. You're always comparing the front window, which means that if the user changes focus (e.g. opens another Terminal window, or switches to another one), the script will check that window instead.

    A solution to that one would be to capture the front window immediately after the do script and use that reference in the repeat loop:

    tell application "Terminal"
        do script "blah"
        set frontWindow to window 1
        repeat until busy of frontWindow is false
            sleep 1
        end repeat
    end tell
  • 4. Re: do script ... please wait
    Noaks Level 1 Level 1 (35 points)
    Ah, sleep! Where does that come from, I need it!?

    Seriously, is "sleep" a valid term?

    But your concern is definitely a valid one, something I've thought about in other instances where I've referenced the front window. In some cases, I've referenced a window id. It's an oversight, but I didn't do so in this case.

    Except for "sleep," I think the following is equivalent to your approach (correct me if I'm wrong):

    tell application "Terminal"
    do script "blah"
    set W_ to windows of application "Terminal" -- must go immediately after "do script" command; I suppose there's a tiny chance someone might slip in a different front window before this line gets executed, so maybe it's not entirely foolproof. But it seems to me that could also occur with your version.
    repeat until busy of (item 1 of W_) is false
    delay 0.1
    end repeat
    end tell


    Message was edited by: Noaks
  • 5. Re: do script ... please wait
    Noaks Level 1 Level 1 (35 points)
    CORRECTION! CORRECTION! CORRECTION!

    Upon further tests of this approach, I found that it was not reliably stalling the AppleScript -- and I determined why as well. This applies to all approaches discussed, whether Camelot's or mine.

    The problem was that, after the "do script" is called, 'set frontWindow to window 1' (Camelot) or 'set W_ to windows of application "Terminal"' (me) may not identify the proper window as window 1 -- time is needed for that window to establish itself. On my computer, with my test script, the threshold is ~0.3 second; using 1 second would be sensible to gain a safety margin. I don't know whether a slow computer might increase the delay needed beyond this.

    Given that, the simple solution is to add a 1-second delay at the appropriate point in the script.

    For Camelot's approach, the script would become:

    tell application "Terminal"
    do script "blah"
    delay 1
    set frontWindow to window 1
    repeat until busy of frontWindow is false
    --sleep 1 (sorry, I find the script won't compile with this!)
    end repeat
    end tell


    For my approach, the script would become:

    tell application "Terminal"
    do script "blah"
    delay 1
    set W_ to windows of application "Terminal"
    repeat until busy of (item 1 of W_) is false
    end repeat
    end tell


    I suppose this slightly increases the chance that someone will slip in a different "window 1." The only solution I can see for that would be to reference the window by its name; but that, too, might be compromised if a different "window 1" has the same name.

    How do you test whether the delay introduced is sufficient? Do this: in a new Script Editor window enter

    tell application "Terminal"
    do script "blah" -- use a command that will take at least a few seconds to execute
    delay 1
    set W_ to windows of application "Terminal"
    repeat until busy of (item 1 of W_) is false
    end repeat
    end tell
    beep 5


    If, upon executing the AppleScript, you get 5 beeps immediately, then the delay is inadequate. The 5 beeps should not occur until Terminal finishes its chore.
  • 6. Re: do script ... please wait
    Camelot Level 8 Level 8 (45,790 points)
    Ah, sleep! Where does that come from, I need it!?


    Oops, my bad. Too many context switches between shell and AppleScript

    delay would be the appropriate command in AppleScript.
  • 7. Re: do script ... please wait
    Camelot Level 8 Level 8 (45,790 points)
    Good catch, Noaks. I'd not noticed that before.

    Upon digging, though, I've come up with an even better revision. It turns out (at least in Leopard, maybe earlier versions, too) that do script actually returns a reference to the window (or tab) where the command is executing.

    It doesn't obviate the need to delay before checking the window status, but it does eliminate any confusion over window ordering, etc.:

    tell application "Terminal"
      set myWindow to do script "sleep 10"
      delay 1
      repeat while (busy of myWindow)
        delay 1
      end repeat
    end tell
  • 8. Re: do script ... please wait
    Pendal Level 1 Level 1 (5 points)
    AHHH ... THANK YOU THANK YOU THANK YOU.

    I have been looking for a solution for over a week.

    This is the first thing that has even remotely showed promise.

    So far it looks like it is working.

    I have about 15,000 tar commands to issues (not exaggerating).

    I will let you know how it works out.