路径问题-POSIX HFS无法获取文件夹

时间:2018-08-18 11:23:04

标签: path applescript osascript

我正在尝试使此简短脚本起作用。它所要做的就是获取本地用户的Application Support / App中的文件夹内容,并将其移至USB。

ffmpeg version 4.0.2 Copyright (c) 2000-2018 the FFmpeg developers
  built with Apple LLVM version 9.1.0 (clang-902.0.39.2)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/4.0.2 --enable-shared --enable-pthreads --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-gpl --enable-libmp3lame --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-libxvid --enable-opencl --enable-videotoolbox --disable-lzma
  libavutil      56. 14.100 / 56. 14.100
  libavcodec     58. 18.100 / 58. 18.100
  libavformat    58. 12.100 / 58. 12.100
  libavdevice    58.  3.100 / 58.  3.100
  libavfilter     7. 16.100 /  7. 16.100
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  1.100 /  5.  1.100
  libswresample   3.  1.100 /  3.  1.100
  libpostproc    55.  1.100 / 55.  1.100

两个目录(USB和计算机)中都存在一个文件夹,该文件夹与此处描述为“ myApp”的自定义路径描述相匹配。该代码在tell的第一部分有错误,无法在应用程序支持中找到该文件夹​​。我不确定为什么会这样,并且我也正在努力了解HFS和POSIX之间的区别,后者是要使用的?我感觉类型可能存在串联错误。我是初学者,请帮忙。

谢谢!

2 个答案:

答案 0 :(得分:1)

了解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路径字符串,   将其识别为不仅是一段文本,而且是文件的路径。的   filealias之间的主要区别在于file是静态的   引用,这意味着如果它指向具有给定名称的文件,并且   该文件的名称更改后,file对象现在将引用一个文件   那不存在。另一方面,alias是动态的   甚至在重命名或移动文件后也可以更改其引用。

     

POSIX file: (如果您应该使用posix路径),POSIX file对象是您的最好朋友。它需要一个posix路径   字符串,并以几乎相同的方式将其限定为文件路径   file用于HFS路径字符串。同样,它是静态引用   并且可以指向不存在的文件或文件夹。

我的推荐

我的感觉是,HFS路径与命令行用户和AppleScripting之间的相互转换很简单,因此不必要。它们确实使人们感到困惑,并且由于从AppleScript返回的结果中可以广泛地观察到该符号,因此它们在使用中似乎是强制性的。

不是。我个人从不使用HFS路径。 (几乎从不)。

一个在本质上并没有比另一个更好,这实际上只是个人喜好。因此,我的建议是选择一种最适合您的样式,并学习如何在AppleScript设置中操纵这种类型的路径。

在使用posix路径时,我自己关心POSIX file对象和alias对象。在此答案的其余部分中,这就是我现在要讨论的重点。

您的脚本

您的脚本引发了第一个错误,因为您试图转义文件路径字符串中的空格,这可能是从终端输入错误的习惯。您不需要对文件字符串中的任何字符进行转义,反斜杠\除外,因为文件路径字符串将始终用双引号引起来。

仍然在解决脚本的第一行,您已经正确地检索了path tolibrary folder(返回了 alias );将其转换为posix路径字符串;然后附加"Application Support/myApp"路径文本。但是,知道您可以实际获得path toapplication support文件夹可能会有所帮助,因此您的第一行可以变成:

set localLocation to POSIX path of (path to application support from user domain) & "myApp"

结果是posix路径 string ,但不是文件对象(但目前还可以)。

您的下一行然后显式声明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对象和posix路径之间存在等效关系。

您可以选择编辑脚本的第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在对象说明符中的作用。< / p>

应该可以将所有文件成功移动到新位置。另一种方法是移动文件夹而不是移动目录,如果有许多文件和子目录,这可能会更快。只需相应地更改目标路径:

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对象:

别名对象

从posix路径构造alias对象非常简单,需要两个步骤。首先,如我上面所示,构造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路径字符串声明您的POSIX file对象,该字符串指向一个不存在的文件,例如您要创建的文件。但是,只能在创建文件后将其强制为alias

您可能要使用alias对象的一个​​原因是因为它们是动态的,正如我之前提到的(或者应该应该是)。因此,如果您在开始时将localLocation设置为alias对象,然后将文件夹移动到它的目的地,就像我上一个 Finder 示例一样,alias object应该现在会自动指向/Volumes/myUsb/myApp/(尽管它并不总是可以成功运行,这是AppleScript的许多错误之一)。

使用alias对象的另一个更重要的原因是,它们直接在AppleScript与之交互的不同应用程序之间进行转换:并非所有人都利用POSIX file对象,有些可能不利用HFS路径;但实际上他们几乎都知道alias对象是什么。

当在 Finder 系统事件之间进行文件处理时,这是关键。一般来说,最好使用系统事件而不是 Finder 完成文件和文件夹的处理。但是,您只能在 Finder 中做几件事:设置文件标签(label index);获取选定的文件(selection);并知道当前哪个目标文件夹具有焦点(insertion location)。

Finder 中检索selection会返回特定于 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对象进行检索要比将它们作为任何其他类对象进行检索要快得多。在我的downloads文件夹的内容上对其进行测试(该文件夹足够小,不会让我等待,但足以让 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 listalias文件对象列表)外,它们是相同的语句。在较大的文件夹上,速度优势将更加明显。

通过 Finder 使用alias对象比使用filePOSIX 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

答案 1 :(得分:1)

我不同意使用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"

但是Finder中的entire contents可能非常慢。外壳要快得多。

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