Проблемы с путями - POSIX HFS не может получить папку
Я пытаюсь заставить этот короткий сценарий работать. Все, что он должен сделать, это взять содержимое папки в Application Support/App локального пользователя и переместить его на usb.
set localLocation to POSIX path of (path to library folder from user domain) & "Application\\ Support/myApp" as text
set usbLocation to "/Volumes/myUsb/myApp"
tell application "Finder" to move entire contents of folder localLocation to folder usbLocation
В обоих каталогах есть папка (USB и компьютер), которая соответствует описанию пользовательского пути, описанному здесь как "myApp". Код содержит ошибку в первом разделе отчета, где он не может найти папку в поддержке приложений. Я не уверен, почему это так, и я также пытаюсь понять разницу между HFS и POSIX, какой из них предназначен для использования? У меня есть ощущение, что возможна ошибка конкатенации с типами. Я новичок, пожалуйста, помогите.
Спасибо!
2 ответа
Понимание того, как AppleScript обращается со ссылками на файлы и папки, является головной болью, и хорошо известно, что он запутан и суетлив относительно спецификаторов файлов и строк путей.
Простые определения:
Posix path:
Путь, состоящий из прямой косой черты, разделяющей папки в дереве каталогов, например/Users/CK/Downloads/Some_File.txt
, Корневой каталог (верхнего уровня) представлен одиночной косой чертой,/
, Каждый путь posix происходит от этого корневого каталога, поэтому, как правило, пути posix должны начинаться с косой черты. В идеале пути к папкам заканчиваются косой чертой; пути к файлам нет; но это не строгое
HFS path:
Путь, состоящий из двоеточий, которые разделяют папки в дереве каталогов, напримерMacintosh HD:Users:CK:Downloads:Some_File.txt
, Корневой каталог представленMacintosh HD:
, который всегда начинается с пути HFS (если только системный жесткий диск не называется другим). В идеале пути к папкам заканчиваются двоеточием; пути к файлам нет; это полужесткий
Это буквально все, что вам нужно знать о путях posix и HFS, чтобы сделать некоторые сценарии AppleScripting. Сложнее всего разобраться с типами классов файлов AppleScript. Есть три:
alias:
Это ваши друзья, и они наиболее универсальны, когда используются с Finder или системными событиями, а также при обращении к файлам или папкам. Это объект AppleScript, который содержит ссылку на файл, которая указывает на существующий файл. Пытаясь назначитьalias
Тип класса для ссылки на файл, который не существует, выдаст ошибку.
file:
Это объект ссылки на файл, который может указывать на файл, который не существует (пока). Он определяет строку пути HFS, определяя ее как не просто фрагмент текста, а путь к файлу. Ключевая разница междуfile
а такжеalias
в том, чтоfile
является статической ссылкой, то есть если она указывает на файл с заданным именем и имя этого файла изменяется,file
объект теперь будет ссылаться на файл, который не существует.alias
с другой стороны, динамически сдвигает свою ссылку даже после переименования или перемещения файла.
POSIX file:
Если вам нравится использовать пути posix (и вы должны),POSIX file
объект твой лучший друг. Он принимает строку пути posix и определяет его как путь к файлу почти таким же образомfile
делает для строк пути HFS. Аналогично, это статическая ссылка и может указывать на файлы или папки, которые не существуют.
Моя рекомендация
Мне кажется, что пути HFS являются ненужным осложнением того, что могло бы быть простым объединением пользователей командной строки и AppleScripting. Они вводят людей в заблуждение, и поскольку нотация так широко соблюдается в результатах, возвращаемых AppleScript, они кажутся обязательными при их использовании.
Они не. Лично я никогда не использую пути HFS. (Почти никогда).
Одно по сути не лучше другого, и это на самом деле просто личное предпочтение. Поэтому я советую выбрать один стиль, который вам наиболее удобен, и научиться управлять этим типом пути в настройках AppleScript.
Поскольку я использую пути posix, я занимаюсь POSIX file
объекты и alias
объекты. Это то, на чем я сосредоточусь сейчас до конца этого ответа.
Ваш сценарий
Ваш скрипт выдал свою первую ошибку, потому что вы пытались избежать пробелов в строке пути к файлу, возможно, из-за привычки печатать в терминале. Вам не нужно экранировать символы в строке файла, кроме обратной косой черты \
, поскольку строки пути к файлу всегда будут заключены в двойные кавычки.
По-прежнему обращаясь к первой строке вашего скрипта, вы совершенно правильно получили path to
library folder
(который возвращает alias
); превратил его в строку пути posix; затем добавил "Application Support/myApp"
текст пути. Тем не менее, может быть полезно знать, что вы можете получить path to
application support
папка, поэтому ваша первая строка может стать:
set localLocation to POSIX path of (path to application support from user domain) & "myApp"
Результатом является строка пути posix, но не файловый объект (но сейчас это нормально).
Ваша следующая строка затем явно объявляет строку пути posix:
set usbLocation to "/Volumes/myUsb/myApp"
что абсолютно нормально.
Немного сложнее: работать с Finder:
tell application "Finder" to move entire contents of ¬
folder localLocation to folder usbLocation
Тем не менее, у вас было почти идеально. Поскольку вы используете пути posix, вам нужно либо превратить их в alias
объекты, или объяснить искателю, что он имеет дело с путём posix, который является то, что POSIX file
объект делает.
Чтобы создать POSIX file
объект, вы можете либо предварять POSIX file
спецификатор строки пути posix, подобный этому:
set usbLocation to POSIX file "/Volumes/myUsb/myApp"
или сделайте более обычное приведение в класс типов, например так:
set usbLocation to "/Volumes/myUsb/myApp" as POSIX file
В любом случае AppleScript превращает это в file
объект и преобразует его в путь HFS. Если вы запустите эту строку чуть выше, AppleScript вернет это:
file "Macintosh HD:Volumes:myUsb:myApp"
Итак, мы уже видим, что есть эквивалентность между file
объекты и пути HFS по сравнению с POSIX file
объекты и пути посикс.
Вы можете редактировать строки 1 и 2 вашего скрипта, чтобы построить эти POSIX file
объекты сразу; или вы можете сделать это в точке, где вы взаимодействуете с Finder:
tell application "Finder" to move entire contents of ¬
folder (localLocation as POSIX file) to folder (usbLocation as POSIX file)
Если вы делаете это здесь, вы должны принудительно использовать as
возможно потому, что добавление его в качестве спецификатора объекта мешает folder
в роли спецификатора объекта.
Это должно успешно переместить все файлы на новое место. Другой способ сделать это - переместить папку вместо ее содержимого, что, вероятно, быстрее, если имеется много файлов и подкаталогов. Просто измените путь назначения соответственно:
set localLocation to POSIX path of (path to application support folder from user domain) & "myApp" as POSIX file
set usbLocation to POSIX file "/Volumes/myUsb/"
tell application "Finder" to move folder localLocation to folder usbLocation with replacing
(with replacing
потому что папка myApp
в месте назначения будет заменена папка myApp
исходя из вашего жесткого диска.)
Наконец, для полноты картины я кратко расскажу о alias
объекты:
Псевдоним объектов
строительство alias
Объекты из путей posix довольно просты и требуют двух шагов. Во-первых, вы строите POSIX file
объект, как я показал вам выше. Затем вы приводите этот объект в alias
, Это можно сделать в одну строку:
set usbLocation to POSIX file "/Volumes/myUsb/myApp" as alias
или же
set usbLocation to "/Volumes/myUsb/myApp" as POSIX file as alias
Помните, однако, что alias
объекты указывают на файлы и папки, которые уже существуют. Поэтому в некоторых случаях вы можете объявить POSIX file
Объект сразу же из строки пути posix, которая указывает на несуществующий файл, который, например, вы будете создавать. Но вы можете только заставить его в alias
после того, как файл был создан.
Одна из причин, вы можете использовать alias
объекты, потому что они являются динамическими, как я упоминал ранее (или они должны быть). Так что если вы установите localLocation
как alias
объекта в начале, затем переместил папку к месту назначения, как в моем последнем примере Finder, alias object
теперь должен автоматически указывать на /Volumes/myUsb/myApp/
(хотя это не всегда работает успешно, как одна из многих ошибок AppleScript).
Другая, более важная причина использования alias
объекты - это то, что они транслируются непосредственно между различными приложениями, с которыми взаимодействует AppleScript: не все используют POSIX file
объекты, а некоторые могут не использовать пути HFS; но они практически все знают, что такое alias
Объект есть.
Это ключ при переключении между Finder и System Events для обработки файлов. Вообще говоря, обработку файлов и папок лучше всего выполнять с помощью системных событий, а не с помощью Finder. Но есть несколько вещей, которые вы можете сделать только в Finder: установить тег файла (label index
); получить выбранные файлы (selection
); и знать, какая целевая папка имеет фокус в настоящее время (insertion location
).
Получение selection
в Finder возвращает специфичные для Finder классы, а именно document files
, Нельзя использовать эти объекты с системными событиями. Тем не менее selection as alias list
это то, что может управляться системными событиями:
tell application "Finder" to set S to selection as alias list
tell application "System Events" to get properties of item 1 of S
Наконец, третья причина использовать alias
объекты, потому что, по некоторым причинам, получение файлов как alias
Объекты заметно быстрее, чем их извлечение, как и любой другой объект класса. Проверка этого на содержимом моей папки загрузок (которая достаточно мала, чтобы не заставлять меня ждать, но достаточно велика, чтобы заставить работать Finder), привела к следующим результатам:
tell application "Finder" to get entire contents of ¬
(path to downloads folder) as alias list
-- 1.45s
tell application "Finder" to get entire contents of ¬
(path to downloads folder)
-- 2.29s
Это идентичные утверждения, за исключением принуждения к alias list
(список alias
файловые объекты) в первую очередь. Преимущество в скорости будет более заметным в больших папках.
использующий alias
объекты с Finder немного легче / проще, чем с file
или же POSIX file
объекты, потому что alias
объекты не различают файлы и папки так, как другие. В вашем скрипте необходимо с Finder использовать folder
спецификатор с POSIX file
объекты; с alias
объект, вам не нужно:
set localLocation to POSIX path of (path to application support folder from user domain) & "myApp" as POSIX file as alias
set usbLocation to POSIX file "/Volumes/myUsb/" as alias
tell application "Finder" to move localLocation to usbLocation with replacing
Я не согласен отговаривать от использования путей HFS.
Если вам нужно использовать Finder, это наиболее удобный способ, так как Finder не принимает пути POSIX.
Для обращения к папке на верхнем уровне внешнего тома в терминологии Finder есть еще один короткий путь: folder "foo" of disk "bar"
,
set localLocation to (path to application support folder from user domain as text) & "myApp"
tell application "Finder" to move entire contents of folder localLocation to folder "myApp" of disk "myUsb"
тем не мение entire contents
в Finder может быть очень медленным. Оболочка намного быстрее.
set localLocation to POSIX path of (path to application support folder from user domain) & "myApp/"
set usbLocation to "/Volumes/myUsb/myApp"
do shell script "/bin/cp " & quoted form of localLocation & "*" & space & quoted form of usbLocation