Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I’m trying to produce an Applescript-based shell command that tells the Preview application from Mac OS X to close a particular window.

#!/bin/sh

osascript <<EOF
tell application "Preview"
   close "$1"
end tell
EOF

But this doesn’t work : I get the error message

25:52: execution error: Preview got an error: "musixdoc.pdf" doesn’t understand the close message. (-1708)

Related question: How do I close an OS X application from the command line using a alias defined in my .bash_profile?

share|improve this question
    
This should work as expected. How are you calling your script, exactly? Note: Your script will not close a particular window. It will quit the application, thus closing all document windows the application might have open. In order to close a particular document the application has opened but not quit the application per se, you need a different script. While most applications quit when their last document window is closed, not all do—this also depends on the version of OS X you're using. –  slhck Jan 1 '13 at 10:01
    
@slhck : "close a particular document the application has opened but not quit the application per se" is exactly what I need. Do you happen to know someplace where such a "different script" is explained? –  Ewan Delanoy Jan 1 '13 at 10:38
add comment

1 Answer 1

up vote 2 down vote accepted

Getting Preview.app to accept AppleScript commands

By default, AppleScripting Preview won't work because Preview is missing the necessary dictionary. To fix this, check Lauri's answer here, which explains setting NSAppleScriptEnabled for Preview.app.

Quit Preview.app, then open a terminal and enter:

sudo defaults write /Applications/Preview.app/Contents/Info NSAppleScriptEnabled -bool true
sudo chmod 644 /Applications/Preview.app/Contents/Info.plist
sudo codesign -f -s - /Applications/Preview.app


Closing a window from an application

1) By window index or name of the window

The command to close a window of any named application would be something like this:

tell application "Preview" to close window 1

… or if you want to close a named document window, e.g. foo.jpg:

tell application "Preview" to close (every window whose name is "foo.jpg")

So, in your shell script that'd be:

#!/bin/sh
osascript <<EOF
tell application "Preview"
  close (every window whose name is "$1")
end tell
EOF

Here, the first argument passed to the script is the name of the window you want to close, e.g. ./quit.sh foo.jpg. Note that if your file contains spaces, you have to quote the filename, e.g. ./quit.sh "foo bar.jpg".

Or if you want to close arbitrary windows from any application, use this:

#!/bin/sh
osascript <<EOF
tell application "$1"
  close (every window whose name is "$2")
end tell
EOF

Here, you'd use ./quit.sh Preview foo.jpg for example.

2) By file name

If you want to close a window that belongs to a certain document, but supplying the file name, you need something else. This is because a multi-page PDF could be displayed as foo.pdf (Page 1 of 42), but you'd just want to pass foo.pdf to the AppleScript.

Here we iterate through the windows and compare the filenames against the argument passed to the script:

osascript <<EOF
tell application "Preview"
    set windowCount to number of windows
    repeat with x from 1 to windowCount
        set docName to (name of document of front window)
        if (docName is equal to "$1") then
            close window x
        end if
    end repeat
end tell
EOF

Now you can simply call ./quit.sh foo.pdf. In a generalized fashion, for all apps with named document windows, that'd be:

osascript <<EOF
tell application "$1"
    set windowCount to number of windows
    repeat with x from 1 to windowCount
        set docName to (name of document of front window)
        if (docName is equal to "$2") then
            close window x
        end if
    end repeat
end tell
EOF


Caveat: Auto-closing Preview.app

Preview.app is one of these applications that automatically quits once its last document window is closed. It does that in order to save memory and "clean up". To disable this behavior, run the following:

defaults write -g NSDisableAutomaticTermination -bool TRUE

Of course, to undo that, change TRUE to FALSE.


Using functions instead of scripts

Finally, I'd suggest putting your scripts into a function that is always available in your shell. To do this, add the scripts to your ~/.bash_profile. Create this file if it doesn't exist.

cw() {
osascript <<EOF
tell application "$1"
    set windowCount to number of windows
    repeat with x from 1 to windowCount
        set docName to (name of document of front window)
        if (docName is equal to "$2") then
            close window x
        end if
    end repeat
end tell
EOF
}

Once you save your bash profile and restart the shell, you can call cw Preview foo.pdf from everywhere.

share|improve this answer
    
I tried this. This time I get no error message, but the script still doesn't work : the window stays visible on screen. –  Ewan Delanoy Jan 1 '13 at 10:43
    
It worked for me. If you open a document in Preview.app, then open AppleScript Editor, and enter tell application "Preview" to windows, does that give you any results? What exact script are you running? –  slhck Jan 1 '13 at 11:38
    
I don’t use the AppleScript editor, I only use "embedded applescript code" in a bash script, as explained in the OP,stored in a .sh file. –  Ewan Delanoy Jan 1 '13 at 12:54
    
In fact, I’m usually quite happy with shell scripts and this is my first applescript. I just did what you advised in your last comment, and got : "{window id 113 of application "Preview"}" as an answer. Is that what I should get? –  Ewan Delanoy Jan 1 '13 at 13:30
    
Also, when I compile << tell application "Preview" to close "musixdoc.pdf" >> with the applescript editor, it does not work either : the musixdoc.pdf window stays visible on the screen. –  Ewan Delanoy Jan 1 '13 at 13:39
show 9 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.