AppleScript:如何检查某物是目录还是文件

发布于 2024-11-27 05:27:17 字数 1213 浏览 0 评论 0原文

更新:下面的解决方案


假设您有一个从 Finder 中选择的项目的列表。假设选择中包含一些文件、文件夹、各种捆绑包,甚至一些应用程序。

现在假设您只需要那些(以 UNIX 术语来说)目录的项目。也就是说,您只需要可以在终端中 cd 找到的项目。

您可以检查每个项目的 kind 属性并查看它是否等于“文件夹”,但这不适用于应用程序捆绑包或其他捆绑包/包,尽管它们实际上是“文件夹”(目录)

如果这些项目是实际的文件对象(不是别名),您可以检查每个项目的 class 属性...不过这并不总是有效,因为捆绑包现在是“文档文件”实例,并且应用程序是“应用程序文件”实例。

如果您只有别名列表而不是实际的文件对象,情况会更糟,因为您无法检查 class 属性;它总是只会说“别名”。

我能想到的唯一解决方案是获取每个项目的 POSIX 路径,并查看它是否有尾部正斜杠,或者将其路径发送到用不同语言编写的脚本,该脚本可以检查某项是否是目录或不。

这两种想法对我来说都很疯狂。检查尾随的正斜杠是非常老套和脆弱的,并且将所有内容提供给不同的脚本完全是矫枉过正。


更新: Asmus 下面的建议似乎是唯一一个好的解决方案,因为 AppleScript 似乎无法自行解决 Strike>:

do shell script "file -b " & filePosixPath

这将返回文件夹、捆绑包、应用程序、包等的字符串“目录”
但请注意(!)对于磁盘,它返回“粘性目录”。

这是一个运行良好的通用函数

on isDirectory(someItem) -- someItem is a file reference
    set filePosixPath to quoted form of (POSIX path of (someItem as alias))
    set fileType to (do shell script "file -b " & filePosixPath)
    if fileType ends with "directory" then return true
    return false
end isDirectory

Update: Solution below


Say you have a list of selected items from Finder. Say there are some files, folders, various bundles, and even some applications included in the selection.

Now say you only want those items that are (in UNIX terms) directories. I.e. you only want items you can cd to in the terminal.

You can check each item's kind property and see if it equals "Folder", but that doesn't work for application bundles or other bundles/packages, though they are in fact "folders" (directories)

If the items are actual file objects (not aliases), you can check each item's class property... except that doesn't always work either, since bundles are now "document file" instances, and applications are "application file" instances.

It's worse if you only have a list of aliases rather than actual file objects, since you can't check the class property; it'll always just say "alias".

The only solutions I can think of, are to either get the POSIX path of each item, and see if it has a trailing forward slash, or to send its path to a script written in a different language, which can check if something's a directory or not.

Both ideas seem crazy to me. Checking for a trailing forward slash is extremely hacky and fragile, and feeding everything to a different script is complete overkill.


Update: What Asmus suggests below does seem to be the only a good solution, as it seems there's no way for AppleScript to figure it out on its own:

do shell script "file -b " & filePosixPath

That'll return the string "directory" for folder, bundles, applications, packages, etc. etc.
But note(!) that for disks, it returns "sticky directory".

Here's a generalized function that works pretty well

on isDirectory(someItem) -- someItem is a file reference
    set filePosixPath to quoted form of (POSIX path of (someItem as alias))
    set fileType to (do shell script "file -b " & filePosixPath)
    if fileType ends with "directory" then return true
    return false
end isDirectory

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

不疑不惑不回忆 2024-12-04 05:27:17

有一个简单的 applescript 解决方案。您可以使用系统事件检查某物是否是“包”。

tell application "Finder" to set theItems to (selection) as alias list

set canCDItems to {}
tell application "System Events"
    repeat with anItem in theItems
        if anItem is package folder or kind of anItem is "Folder" or kind of anItem is "Volume" then
            set end of canCDItems to contents of anItem
        end if
    end repeat
end tell
return canCDItems

There is a simple applescript solution. You can check if something is a "package" using system events.

tell application "Finder" to set theItems to (selection) as alias list

set canCDItems to {}
tell application "System Events"
    repeat with anItem in theItems
        if anItem is package folder or kind of anItem is "Folder" or kind of anItem is "Volume" then
            set end of canCDItems to contents of anItem
        end if
    end repeat
end tell
return canCDItems
给妤﹃绝世温柔 2024-12-04 05:27:17

如果变量只是一个字符串,请使用以下形式:

on isDirectory(someItem) -- someItem is a string
    set filePosixPath to quoted form of (POSIX path of someItem)
    set fileType to (do shell script "file -b " & filePosixPath)
    if fileType ends with "directory" then return true
    return false
end isDirectory

If the variable is just a string, use this form:

on isDirectory(someItem) -- someItem is a string
    set filePosixPath to quoted form of (POSIX path of someItem)
    set fileType to (do shell script "file -b " & filePosixPath)
    if fileType ends with "directory" then return true
    return false
end isDirectory
秋心╮凉 2024-12-04 05:27:17

我正在使用 alfred 工作流程,该工作流程通过键盘组合键 (⎇+F2) 运行此脚本。
该脚本根据我在查找器上选择的内容打开一个终端应用程序,如果是一个文件夹,则在所选文件夹内打开一个终端,如果是一个文件,则在父文件夹上打开一个终端。
工作完美

set pathList to "~"
if frontmost of application "Finder" then
    tell application "Finder"
        set fileList to selection as alias list
        if fileList is not equal to {} then
            set someItem to (item 1 of fileList) as text
            set filePosixPath to quoted form of (POSIX path of someItem)
            set fileType to (do shell script "file -b " & filePosixPath)
            if fileType ends with "directory" then
                set pathList to filePosixPath
            else
                set pathList to (quoted form of POSIX path of (folder of the front window as alias))
            end if
        else
            set pathList to (quoted form of POSIX path of (folder of the front window as alias))
        end if
        
    end tell
end if
tell application "System Events"
    tell application "Terminal"
        activate
        if exists window 1 then
            do script ("cd " & pathList) in window 1
        else
            do script ("cd " & pathList)
        end if
    end tell
end tell

Im using an alfred workflow which run this script with a keyboard combination of keys (⎇+F2).
The script opens a terminal application based on what I got selected on finder, if is a folder then open a terminal inside selected folder, if is a file then open a terminal on parent folder.
worked flawless

set pathList to "~"
if frontmost of application "Finder" then
    tell application "Finder"
        set fileList to selection as alias list
        if fileList is not equal to {} then
            set someItem to (item 1 of fileList) as text
            set filePosixPath to quoted form of (POSIX path of someItem)
            set fileType to (do shell script "file -b " & filePosixPath)
            if fileType ends with "directory" then
                set pathList to filePosixPath
            else
                set pathList to (quoted form of POSIX path of (folder of the front window as alias))
            end if
        else
            set pathList to (quoted form of POSIX path of (folder of the front window as alias))
        end if
        
    end tell
end if
tell application "System Events"
    tell application "Terminal"
        activate
        if exists window 1 then
            do script ("cd " & pathList) in window 1
        else
            do script ("cd " & pathList)
        end if
    end tell
end tell
星光不落少年眉 2024-12-04 05:27:17

我今天需要这个,因为我试图将几个差异工具插入到 Mountain Lion 的 Finder 中,并想要检查所选的一个或多个项目是否是文件夹或文件。这对我有用:

tell application "Finder"
  set sel1 to the selection
  set class1 to class of (item 1 of sel1)
  set cs to (class1 as string)
  ...
  if cs = "folder" or cs contains "class cfol" then
    set choice to display alert "Which tool?" buttons {"opendiff", "diffmerge"}
    set tool to (button returned of choice)

我发现我需要测试这两种情况的 cs,具体取决于我是在 AppleScript 编辑器中运行还是单击 Finder 上的工具栏按钮的结果。远不是最简洁的,但比之前仅使用 AppleScript 的解决方案更短,这将是我的替代提案

on isDirectory(someItem)
  ((class of someItem) as string) contains "fol"
end isDirectory

欢迎在所有情况下进行全面测试的结果!

I needed this today, as I was trying to plug a couple of diff tools into Finder for Mountain Lion and wanted to check if the selected item or items were folders or files. This worked for me:

tell application "Finder"
  set sel1 to the selection
  set class1 to class of (item 1 of sel1)
  set cs to (class1 as string)
  ...
  if cs = "folder" or cs contains "class cfol" then
    set choice to display alert "Which tool?" buttons {"opendiff", "diffmerge"}
    set tool to (button returned of choice)

I found I needed to test cs for both cases, depending on whether I was running in the AppleScript Editor or as a result of clicking a toolbar button on Finder. Far from the neatest but, shorter than the previous AppleScript-only solution, this would be my alternative proposal

on isDirectory(someItem)
  ((class of someItem) as string) contains "fol"
end isDirectory

Results of full testing in all circumstances welcome!

謸气贵蔟 2024-12-04 05:27:17

标准添加提供了此功能(无需系统事件):

set isBundleType to package folder of (info for (choose file))

Standard Additions offers this (no System Events necessary):

set isBundleType to package folder of (info for (choose file))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文