Я пытаюсь создать команду оболочки на основе AppleScript, которая прикажет приложению Preview из Mac OS X закрыть определенное окно.
#!/bin/sh
osascript <<EOF
tell application "Preview"
close "$1"
end tell
EOF
Но это не работает: я получаю сообщение об ошибке
25:52: execution error: Preview got an error: "musixdoc.pdf" doesn’t understand the close message. (-1708)
Сопутствующий вопрос:Как закрыть приложение OS X из командной строки, используя псевдоним, определенный в моем .bash_profile?
решение1
Заставляем Preview.app принимать команды AppleScript
По умолчанию AppleScripting Preview не будет работать, поскольку Preview не хватает необходимого словаря. Чтобы исправить это, проверьтеОтвет Лаури здесь, который объясняет настройку NSAppleScriptEnabled
Preview.app.
Закройте Preview.app, затем откройте терминал и введите:
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
Закрытие окна из приложения
1) По индексу окна или названию окна
Команда для закрытия окна любого именованного приложения будет выглядеть примерно так:
tell application "Preview" to close window 1
… или если вы хотите закрыть именованное окно документа, например foo.jpg
:
сказать приложению "Предварительный просмотр" закрыть (каждое окно с именем "фу.jpg")
Итак, в вашем скрипте оболочки это будет выглядеть так:
#!/bin/sh
osascript <<EOF
tell application "Preview"
close (every window whose name is "$1")
end tell
EOF
Здесь первый аргумент, передаваемый скрипту, — это имя окна, которое вы хотите закрыть, например ./quit.sh foo.jpg
. Обратите внимание, что если ваш файл содержит пробелы, вам необходимо заключить имя файла в кавычки, например ./quit.sh "foo bar.jpg"
.
Или, если вы хотите закрыть произвольные окна любого приложения, используйте это:
#!/bin/sh
osascript <<EOF
tell application "$1"
close (every window whose name is "$2")
end tell
EOF
Здесь вы могли бы использовать, ./quit.sh Preview foo.jpg
например.
2) По имени файла
Если вы хотите закрыть окно, которое принадлежит определенному документу, но при этом указываете имя файла, вам нужно что-то еще. Это потому, что многостраничный PDF может отображаться как foo.pdf (Page 1 of 42)
, но вы просто хотите передать foo.pdf
его AppleScript.
Здесь мы перебираем окна и сравниваем имена файлов с аргументом, переданным скрипту:
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
Теперь вы можете просто вызвать ./quit.sh foo.pdf
. В общем случае для всех приложений с именованными окнами документов это будет выглядеть так:
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
Предупреждение: автоматическое закрытие Preview.app
Preview.app — одно из таких приложений, которое автоматически завершает работу после закрытия последнего окна документа. Это делается для экономии памяти и «очистки». Чтобы отключить это поведение, выполните следующее:
defaults write -g NSDisableAutomaticTermination -bool TRUE
Конечно, чтобы отменить это, измените TRUE
на FALSE
.
Использование функций вместо скриптов
Наконец, я бы предложил поместить ваши скрипты в функцию, которая всегда доступна в вашей оболочке. Чтобы сделать это, добавьте скрипты в ваш ~/.bash_profile
. Создайте этот файл, если он не существует.
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
}
После сохранения профиля bash и перезапуска оболочки вы сможете совершать вызовы cw Preview foo.pdf
откуда угодно.
решение2
Ответ slhck выглядит хорошим и исчерпывающим.Осторожно, выполнение третьей строки кода:
sudo codesign -f -s - /Applications/Preview.app
«похоже», что это приводило к сбою Preview при каждом запуске из-за следующего:
Application Specific Information:
XPC domain creation failed: The code signature is not valid: The operation couldn’t be completed. (OSStatus error -67061.)
Согласно руководству по кодированию, это -f
означает принудительное «заменение существующей подписи кодовым знаком» и -s
«подписание кода по указанному пути»… в данном случае-
Судя по всему, Preview теперь неправильно подписан и непригоден для использования. :(