Передача переменных из bash в applecript - не может быть преобразован в текстовый тип. (-1700) Ошибка - PullRequest
0 голосов
/ 16 апреля 2019

Я пытаюсь сделать скрипт в automator для автоматизации некоторых скриптов оболочки.Я хочу, чтобы местоположение папки было динамическим.Мне удалось передать переменную из bash в applecript, но applecript выдает ошибку типа (-1700) «Невозможно преобразовать тип в текст».Чего мне здесь не хватает?

x="/"
my_command="cd $x"
osascript -e 'on run my_command' -e \
'tell application "Terminal"
    do shell script my_command
    activate
end tell' -e 'end run' $my_command

Здесь команда ('cd /') не запускается и выдает следующую ошибку типа.

47:67: execution error: Terminal got an error: Can’t make {"cd", "/"} into type text. (-1700)

1 Ответ

0 голосов
/ 17 апреля 2019

Я предполагаю, что ваш кодовый блок используется внутри действия Automator Run Shell Script (что важно включить в ваш вопрос для дальнейшего использования).Работая над этим предположением для решения вашего конкретного запроса, необходимо учитывать две небольшие особенности в отношении переменных в bash и AppleScript:

  1. В bash оболочка будет обрабатывать расширения параметров (например, использование переменной $my_command в качестве параметра для osascript в последней строке вашего сценария) и подстановок команд (где переменная используется аналогичным образомдля параметра, за исключением того, что он содержит команду оболочки), и выполняет то, что называется разбиение слов .Как следует из названия, он разбивает текст на слова, хотя в контексте сценариев оболочки, слово ограничивается любым символом, определенным переменной среды $IFS.Вы можете прочитать об этом больше сами, если вам это особенно интересно, но то, что это делает в вашем сценарии, - это то, что вы можете предсказать из того, что называется разбиение слов : оно разбивает "cd /" в пустом пространстве и обеспечиваетдва отдельных поля для каждого слова, таким образом передавая два аргумента osascript, а не один аргумент, который вы намеревались.

  2. В AppleScript параметры передаются вОбработчик run может быть определен в двух общих синтаксических формах.Первый:

    on run args
    

    , где args - это переменная, которая будет заполнена неопределенным количеством аргументов (которые могут быть нулевыми), переданными ей и генерирующими объект list, гдекаждый item в списке является одним из аргументов (порядок сохраняется).

    Вторая синтаксическая форма включает в себя переменные идентификаторы в фигурных скобках для объявления списка с фиксированным числом параметров:

    on run {arg}
    

    Здесь {arg} - это отдельный элемент list, определяющий точное количество аргументов (в данном случае один), которые будут переданы в переменную arg.Передача менее одного аргумента приведет к ошибке в AppleScript;передача more сохранит первый аргумент в arg, отбрасывая остальные.Ожидается объявление двух аргументов:

    on run {_1, _2}
    

    , где первый параметр передается в переменную _1, а второй передается в переменную _2 (выбор имен переменных во всех этихпримеры не имеют никакого значения, кроме символического, но они также являются примерами допустимых идентификаторов переменных AppleScript).Передача менее двух параметров вызовет ошибку;передача более двух приведет к уничтожению всех параметров, кроме первых двух.

    Вы можете следовать тем же правилам, что и при увеличении количества параметров, объявленных в обработчике, в общем виде:

    on run {a, b, c, ...}
    

    Обратите внимание, что, кроме того, эти переменные могут сами по себе содержать list объектов. Следовательно, в то время как on run {arg} получит единственный аргумент, сохраненный в переменной arg, этот аргумент может быть списком, содержащим несколько элементов.


Принимая во внимание эти две особенности двух разных языков, возможно, вы сможете увидеть, что произошло: $my_command подвергается расширению параметров, разбивая его на два параметра, "cd" и "/", которые передаются в osascript;osascript интерпретирует каждый отдельный параметр как item в list для отправки в обработчик run.К счастью, вы использовали первый синтаксис обработчика AppleScript run при объявлении вашего параметра как list объекта неопределенной длины.

Это позволило переменной AppleScript my_command передать список из двух элементов, т.е.{"cd", "/"}.Это приемлемо, если вы знаете, как вы хотите обрабатывать элементы в списке: в этом случае вы захотите объединить их с разделителем пробела;прямой путь будет выглядеть так:

item 1 of my_command & space & item 2 of my_command --> "cd /"

Поскольку это не было сделано, do shell script (что, в любом случае, является неправильной командой) получил объект list в качестве прямого параметра , тогда как он ожидает text (string) object.

Возможно, я бы решил исправить эту конкретную проблему, чтобы предотвратить разбиение слов в bash.Способ сделать это - заключить параметр в двойные кавычки:

osascript -e 'on run my_command' ... -e 'end run' "$my_command"

Двойные кавычки говорят оболочке обрабатывать все внутри как одно слово, поэтому теперь переменная AppleScript my_command получает один аргумент.Технически это все еще список, содержащий один элемент, но большинство команд, которые ожидают, что text объекты способны вести себя разумно, когда он получает список из одного элемента, содержащий строку.

Затем, как заметил @ user3439894в комментарии вы должны заменить do shell script на do script, и он выполнит команду "cd /" в новом Terminal tab / window.

Скорректированный скрипт, реализующий это исправлениеможет выглядеть примерно так:

x="/"
my_command="cd $x"

osascript -e '
    on run my_command
        tell application "Terminal"
            do script my_command
            activate
        end tell
    end run' "$my_command"

С учетом всего вышесказанного, в этой ситуации было бы разумнее использовать вместо этого действие Запуск AppleScript , которое будет выглядеть следующим образом:это:

on run {my_command, null}
    tell application "Terminal"
        do script my_command
        activate
    end tell
end run

Здесь я заявляю, что обработчику run нужно передать ровно два параметра:

Второй - что-то специфическое для Automator ,в котором обычно есть образец кода, готовый для хранения второго аргумента в переменной с именем parameters.Этот аргумент передается Automator , поэтому вам не нужно беспокоиться о том, откуда он исходит.Он содержит информацию о локальном каталоге, связанную с запуском этого экземпляра скрипта.Это не особенно полезно в любых ситуациях, с которыми я когда-либо сталкивался, и, конечно, не в этой.Я предпочитаю уничтожить информацию, объявив второй параметр как null.

. Это оставляет нам только один параметр, но этот параметр будет получен в виде list,который я бы порекомендовал - вначале, прежде чем вы решите, что вам нужно больше сложности - ограничиться одним элементом, который будет строкой, содержащей ваше выражение bash.

Это может быть передано в Запуск AppleScript действие любым действием, предшествующим ему, которое я рекомендую либо в виде простого текста;переменная Automator ;или что-то специфическое для природы параметра (в этом случае, каталог, предлагающий действие Finder , будет уместным).Если вы хотите сохранить каталог динамическим, Получить выбранные элементы Finder будет одним из примеров того, как передать Automator a Finder путь, и он станетпараметр передан в AppleScript.

Поэтому я собираюсь внести несколько небольших изменений, начиная с введения команды cd в AppleScript, чтобы избавить вас от необходимости путаться с дополнительным Automator действия и выработать способы их правильного сочетания.Я также собираюсь изменить выражение параметра обработчика run:

on run {{filepath}, null}
    local filepath

    set filepath to the POSIX path of ([filepath, "::"] as text)

    tell application "Terminal"
        do script "cd " & the quoted form of the filepath
        activate
    end tell
end run

Automator Workflow in macOS 10.13

Этот рабочий процесс теперь получает путь к файлу для какого файла,папку или элементы, которые вы выбрали в Finder , и открывает окно Terminal , чтобы указать свой рабочий каталог на папку, в которой находятся выбранные файлы.

Это ни в коем случае не иллюстрирует идеальную реализацию этого (и, напротив, в macOS есть встроенный сервис для открытия окна Terminal , указывающего на текущую открытую папку в Finder ).Но для 5-строчного блока кода AppleScript, который связывается с оболочкой, это выполнимо.

Это изящное и дикое выражение для моего объявления параметров:

on run {{filepath}, null}

добавлены фигурные скобки вокруг параметра filepath, ограничив его тем самым одним унарным аргументом пути к файлу.Это избавляет от необходимости беспокоиться о том, что происходит при множественном выборе, поскольку сохраняется только первый элемент в выборе.Это означает, что если не выбрать ни одного элемента и запустить сценарий, возникнет ошибка, но если удалить фигурные скобки (множественный выбор, вызывающий ошибку), произойдет обратное.

Существует множество способов для успешного управления всеми сценариями,но этот ответ вышел бы за рамки того, что было изначально задумано.

...