Estou tentando produzir um comando shell baseado em Applescript que informa ao aplicativo Preview do Mac OS X para fechar uma janela específica.
#!/bin/sh
osascript <<EOF
tell application "Preview"
close "$1"
end tell
EOF
Mas isso não funciona: recebo a mensagem de erro
25:52: execution error: Preview got an error: "musixdoc.pdf" doesn’t understand the close message. (-1708)
Pergunta relacionada:Como fecho um aplicativo OS X na linha de comando usando um alias definido em meu .bash_profile?
Responder1
Fazendo com que Preview.app aceite comandos AppleScript
Por padrão, o AppleScripting Preview não funcionará porque o Preview não possui o dicionário necessário. Para corrigir isso, verifiqueA resposta de Lauri aqui, que explica a configuração NSAppleScriptEnabled
de Preview.app.
Saia do Preview.app, abra um terminal e digite:
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
Fechando uma janela de um aplicativo
1) Por índice da janela ou nome da janela
O comando para fechar uma janela de qualquer aplicativo nomeado seria algo assim:
tell application "Preview" to close window 1
… ou se você quiser fechar uma janela de documento nomeada, por exemplo foo.jpg
:
diga ao aplicativo "Preview" para fechar (todas as janelas cujo nome é "foo.jpg")
Então, no seu script de shell seria:
#!/bin/sh
osascript <<EOF
tell application "Preview"
close (every window whose name is "$1")
end tell
EOF
Aqui, o primeiro argumento passado para o script é o nome da janela que você deseja fechar, por exemplo ./quit.sh foo.jpg
. Observe que se o seu arquivo contiver espaços, você deverá citar o nome do arquivo, por exemplo ./quit.sh "foo bar.jpg"
, .
Ou se você quiser fechar janelas arbitrárias de qualquer aplicativo, use isto:
#!/bin/sh
osascript <<EOF
tell application "$1"
close (every window whose name is "$2")
end tell
EOF
Aqui, você usaria, ./quit.sh Preview foo.jpg
por exemplo.
2) Por nome de arquivo
Se quiser fechar uma janela que pertence a um determinado documento, mas fornecendo o nome do arquivo, você precisa de outra coisa. Isso ocorre porque um PDF de várias páginas pode ser exibido como foo.pdf (Page 1 of 42)
, mas você deseja apenas passar foo.pdf
para o AppleScript.
Aqui iteramos pelas janelas e comparamos os nomes dos arquivos com o argumento passado ao 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 window x)
if (docName is equal to "$1") then
close window x
end if
end repeat
end tell
EOF
Agora você pode simplesmente ligar ./quit.sh foo.pdf
. De forma generalizada, para todos os aplicativos com janelas de documentos nomeadas, seria:
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 window x)
if (docName is equal to "$2") then
close window x
end if
end repeat
end tell
EOF
Advertência: Preview.app de fechamento automático
Preview.app é um desses aplicativos que fecha automaticamente quando a última janela do documento é fechada. Ele faz isso para economizar memória e “limpar”. Para desativar esse comportamento, execute o seguinte:
defaults write -g NSDisableAutomaticTermination -bool TRUE
Claro, para desfazer isso, mude TRUE
para FALSE
.
Usando funções em vez de scripts
Por fim, sugiro colocar seus scripts em uma função que esteja sempre disponível em seu shell. Para fazer isso, adicione os scripts ao seu arquivo ~/.bash_profile
. Crie este arquivo se ele não existir.
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 window x)
if (docName is equal to "$2") then
close window x
end if
end repeat
end tell
EOF
}
Depois de salvar seu perfil bash e reiniciar o shell, você poderá ligar cw Preview foo.pdf
de qualquer lugar.
Responder2
A resposta do slhck parece boa e completa.Cuidado, executando a terceira linha de código:
sudo codesign -f -s - /Applications/Preview.app
'parece' ter causado a falha do Preview em cada inicialização com o seguinte:
Application Specific Information:
XPC domain creation failed: The code signature is not valid: The operation couldn’t be completed. (OSStatus error -67061.)
De acordo com o manual de codesign, isso -f
força o 'sinal de código a substituir a assinatura existente' e é -s
'assinar o código no caminho fornecido'… neste caso-
Aparentemente, o Preview agora está assinado incorretamente e inutilizável. :(