使用 AppleScript 获取完整目录内容

发布于 2024-08-18 14:26:09 字数 41 浏览 9 评论 0原文

我需要将文件夹及其子文件夹的全部(可见)内容作为列表获取。这可能吗?

I need to get the entire (visible) contents of a folder and its subfolders as a list. Is this possible?

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

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

发布评论

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

评论(4

策马西风 2024-08-25 14:26:09

看看这有多容易,

  tell application "Finder"
     set file_list to entire contents of (choose folder with prompt "Please select directory.")
   end tell 

如果您想要一个文件名列表,那么您可以这样做是

  tell application "Finder"
    set file_list to name of every file of entire contents of (choose folder with prompt "Please select directory.")
   end tell

的,整个内容完全按照您所说的进行 - 但它很容易让人窒息
大文件夹,并且需要很长时间。没关系
小事情,例如从您的文件夹中提取一种类型的所有文件
知道只会​​包含少量文件。

递归方法也很好用——但它使用“列表文件夹”,并且
它的字典列表表明它已被弃用,我们不应该使用它
不再有。

see how easy this can be

  tell application "Finder"
     set file_list to entire contents of (choose folder with prompt "Please select directory.")
   end tell 

if you want a list of file names then you could do this

  tell application "Finder"
    set file_list to name of every file of entire contents of (choose folder with prompt "Please select directory.")
   end tell

Yes, entire contents does exactly what you say -- but it easily chokes on
large folders, and takes forever. It's OK for
small things, like extracting all the files of one kind out of a folder you
know will only contain a small number of files.

The recursive method also works well -- but it's using "list folder", and
the dictionary listing for it says it's deprecated and we shouldn't use it
any more.

赠佳期 2024-08-25 14:26:09

我确信有一个 shell 命令可以更快地完成此操作,但这是纯 Applescript 中的一种方法,可以让您完全控制要显示的信息的格式。

property kFileList : {}

tell application "Finder"
    set source_folder to choose folder with prompt "Please select directory."
    my createList(source_folder)
end tell

on createList(item_list)
    set the the_items to list folder item_list without invisibles
    set item_list to item_list as string
    repeat with i from 1 to number of items in the the_items
        set the_item to item i of the the_items
        set the_item to (item_list & the_item) as alias
        set this_info to info for the_item
        set file_name to name of this_info
        set end of kFileList to file_name
        if folder of this_info is true then
            my createList(the_item)
        end if
    end repeat
end createList

顺便说一句,还有许多文件列表应用程序可以比 Applescript 更快地完成此操作。

更新:作为本次讨论的结果,该函数再次出现,但这次使用更新的 API。这可能需要一些清理工作,但它可以轻松地对我的桌面进行编目(这对我来说是一个很深很深的文件夹):

property kFileList : {}

tell application "Finder"
    set source_folder to choose folder with prompt "Please select directory."
    my createList(source_folder)
end tell

return kFileList

on createList(mSource_folder)
    set item_list to ""
    
    tell application "System Events"
        set item_list to get the name of every disk item of mSource_folder
    end tell
    
    set item_count to (get count of items in item_list)
    
    repeat with i from 1 to item_count
        set the_properties to ""
        
        set the_item to item i of the item_list
        set the_item to ((mSource_folder & the_item) as string) as alias
        
        tell application "System Events"
            set file_info to get info for the_item
        end tell
        
        if visible of file_info is true then
            set file_name to displayed name of file_info
            set end of kFileList to file_name
            if folder of file_info is true then
                my createList(the_item)
            end if
        end if
        
    end repeat
end createList

I'm sure there is a shell command that can do this faster, but here is one way in pure Applescript that gives you total control over formatting what info you would like displayed.

property kFileList : {}

tell application "Finder"
    set source_folder to choose folder with prompt "Please select directory."
    my createList(source_folder)
end tell

on createList(item_list)
    set the the_items to list folder item_list without invisibles
    set item_list to item_list as string
    repeat with i from 1 to number of items in the the_items
        set the_item to item i of the the_items
        set the_item to (item_list & the_item) as alias
        set this_info to info for the_item
        set file_name to name of this_info
        set end of kFileList to file_name
        if folder of this_info is true then
            my createList(the_item)
        end if
    end repeat
end createList

On a side note, there are also a number file listing applications that can do this faster than Applescript.

UPDATE: As a result of this discussion, here is the function again, but this time using the updated API. This could probably could use some cleaning up, but it works cataloging my Desktop handily enough (and that's a deep, deep folder for me):

property kFileList : {}

tell application "Finder"
    set source_folder to choose folder with prompt "Please select directory."
    my createList(source_folder)
end tell

return kFileList

on createList(mSource_folder)
    set item_list to ""
    
    tell application "System Events"
        set item_list to get the name of every disk item of mSource_folder
    end tell
    
    set item_count to (get count of items in item_list)
    
    repeat with i from 1 to item_count
        set the_properties to ""
        
        set the_item to item i of the item_list
        set the_item to ((mSource_folder & the_item) as string) as alias
        
        tell application "System Events"
            set file_info to get info for the_item
        end tell
        
        if visible of file_info is true then
            set file_name to displayed name of file_info
            set end of kFileList to file_name
            if folder of file_info is true then
                my createList(the_item)
            end if
        end if
        
    end repeat
end createList
眼中杀气 2024-08-25 14:26:09

哇,这已经很晚了,但我检查了一下,它有效。

tell application "Finder" to set folder_root to (choose folder with prompt "Please select directory.")

set fl to {}
dump_folder(folder_root)

on dump_folder(f)
    global fl
    tell application "System Events" to set end of fl to (get the POSIX path of f)
    tell application "Finder" to set nfl to (the items of the contents of f)
    repeat with nf in nfl
        dump_folder(nf as alias)
    end repeat
end dump_folder

fl

Wow this is quite late but I checked and it works.

tell application "Finder" to set folder_root to (choose folder with prompt "Please select directory.")

set fl to {}
dump_folder(folder_root)

on dump_folder(f)
    global fl
    tell application "System Events" to set end of fl to (get the POSIX path of f)
    tell application "Finder" to set nfl to (the items of the contents of f)
    repeat with nf in nfl
        dump_folder(nf as alias)
    end repeat
end dump_folder

fl
日裸衫吸 2024-08-25 14:26:09

对于那些不关心脚本的紧凑性但关心巨大速度的人来说,AsObjC 版本(由 @Shane Stanley 编写,谢谢):

use AppleScript version "2.4"
use framework "Foundation"
use scripting additions

-- classes, constants, and enums used
property NSMutableArray : a reference to current application's NSMutableArray
property NSURLIsDirectoryKey : a reference to current application's NSURLIsDirectoryKey
property |NSURL| : a reference to current application's |NSURL|
property NSFileManager : a reference to current application's NSFileManager
property NSURLIsPackageKey : a reference to current application's NSURLIsPackageKey
property NSURLPathKey : a reference to current application's NSURLPathKey
property NSArray : a reference to current application's NSArray
property NSString : a reference to current application's NSString

set theFolder to POSIX path of (path to movies folder)
my entireContentsOf:theFolder includeInvisibles:false includeFiles:true includeFolders:true resultType:"paths"


-- Returns the entire contents of a folder and its subfolders.
-- If includeFolders is false, only files (including packages) will be returned.
-- If includeFiles is false, only folders will be returned. 
-- The resultType parameter takes a string:, "paths" to get POSIX paths, "names" to get just the names, "POSIX names" to get POSIX names (the / character appears as a :), "urls" to get an array of NSURLs, or "files" to get AppleScript file references. The latter is only available under macOS 10.11 and later.
on entireContentsOf:aFileOrPath includeInvisibles:incInvis includeFiles:incFiles includeFolders:incFolders resultType:resType
    set theURL to my makeURLFromFileOrPath:aFileOrPath
    set theOptions to 2 -- NSDirectoryEnumerationSkipsPackageDescendants
    if not incInvis then set theOptions to 6 -- NSDirectoryEnumerationSkipsHiddenFiles
    set theEnumerator to NSFileManager's |defaultManager|()'s enumeratorAtURL:theURL includingPropertiesForKeys:{} options:theOptions errorHandler:(missing value)
    set theURLs to theEnumerator's allObjects()
    if not incFolders then
        set theURLs to my filesAndPackagesInURLArray:theURLs
    else if not incFiles then
        set theURLs to my foldersInURLArray:theURLs
    end if
    return my convertURLs:theURLs resultType:resType
end entireContentsOf:includeInvisibles:includeFiles:includeFolders:resultType:


-- This handler is called by other handlers
on makeURLFromFileOrPath:theFileOrPathInput
    -- make it into a Cocoa object for easier comparison
    set theFileOrPath to (NSArray's arrayWithObject:theFileOrPathInput)'s firstObject()
    if (theFileOrPath's isKindOfClass:(NSString)) as boolean then
        if (theFileOrPath's hasPrefix:"/") as boolean then -- full POSIX path
            return |NSURL|'s fileURLWithPath:theFileOrPath
        else if (theFileOrPath's hasPrefix:"~") as boolean then -- POSIX path needing ~ expansion
            return |NSURL|'s fileURLWithPath:(theFileOrPath's |stringByExpandingTildeInPath|())
        else -- must be HFS path
            return |NSURL|'s fileURLWithPath:(POSIX path of theFileOrPathInput)
        end if
    else if (theFileOrPath's isKindOfClass:(|NSURL|)) as boolean then -- happens with files and aliases in 10.11
        return theFileOrPath
    else -- must be a file or alias
        return |NSURL|'s fileURLWithPath:(POSIX path of theFileOrPathInput)
    end if
end makeURLFromFileOrPath:


-- This handler is called by other handlers
on filesAndPackagesInURLArray:theURLs
    set AsObjCTrue to current application's NSNumber's numberWithBool:true
    set itemURLs to NSMutableArray's array()
    repeat with aURL in theURLs -- is it a directory?
        set {theResult, theValue, theError} to (aURL's getResourceValue:(reference) forKey:NSURLIsDirectoryKey |error|:(reference))
        if theValue = AsObjCTrue then -- is it a package?
            set {theResult, theValue, theError} to (aURL's getResourceValue:(reference) forKey:NSURLIsPackageKey |error|:(reference))
            if theValue = AsObjCTrue then (itemURLs's addObject:aURL)
        else
            (itemURLs's addObject:aURL)
        end if
    end repeat
    return itemURLs
end filesAndPackagesInURLArray:


-- This handler is called by other handlers
on convertURLs:theURLs resultType:resType
    considering numeric strings
        if resType = "names" then
            return ((((theURLs's valueForKey:"lastPathComponent")'s componentsJoinedByString:(character id 0))'s stringByReplacingOccurrencesOfString:":" withString:"/")'s componentsSeparatedByString:(character id 0)) as list
        else if resType = "POSIX names" then
            return (theURLs's valueForKey:"lastPathComponent") as list
        else if resType = "urls" then
            return theURLs
        else if resType = "files" and AppleScript's version > "2.4" then
            return theURLs as list
        else
            return (theURLs's valueForKey:"path") as list
        end if
    end considering
end convertURLs:resultType:

For those who care not about the compactness of the script, but the huge speed, the AsObjC version (written by @Shane Stanley, thanks):

use AppleScript version "2.4"
use framework "Foundation"
use scripting additions

-- classes, constants, and enums used
property NSMutableArray : a reference to current application's NSMutableArray
property NSURLIsDirectoryKey : a reference to current application's NSURLIsDirectoryKey
property |NSURL| : a reference to current application's |NSURL|
property NSFileManager : a reference to current application's NSFileManager
property NSURLIsPackageKey : a reference to current application's NSURLIsPackageKey
property NSURLPathKey : a reference to current application's NSURLPathKey
property NSArray : a reference to current application's NSArray
property NSString : a reference to current application's NSString

set theFolder to POSIX path of (path to movies folder)
my entireContentsOf:theFolder includeInvisibles:false includeFiles:true includeFolders:true resultType:"paths"


-- Returns the entire contents of a folder and its subfolders.
-- If includeFolders is false, only files (including packages) will be returned.
-- If includeFiles is false, only folders will be returned. 
-- The resultType parameter takes a string:, "paths" to get POSIX paths, "names" to get just the names, "POSIX names" to get POSIX names (the / character appears as a :), "urls" to get an array of NSURLs, or "files" to get AppleScript file references. The latter is only available under macOS 10.11 and later.
on entireContentsOf:aFileOrPath includeInvisibles:incInvis includeFiles:incFiles includeFolders:incFolders resultType:resType
    set theURL to my makeURLFromFileOrPath:aFileOrPath
    set theOptions to 2 -- NSDirectoryEnumerationSkipsPackageDescendants
    if not incInvis then set theOptions to 6 -- NSDirectoryEnumerationSkipsHiddenFiles
    set theEnumerator to NSFileManager's |defaultManager|()'s enumeratorAtURL:theURL includingPropertiesForKeys:{} options:theOptions errorHandler:(missing value)
    set theURLs to theEnumerator's allObjects()
    if not incFolders then
        set theURLs to my filesAndPackagesInURLArray:theURLs
    else if not incFiles then
        set theURLs to my foldersInURLArray:theURLs
    end if
    return my convertURLs:theURLs resultType:resType
end entireContentsOf:includeInvisibles:includeFiles:includeFolders:resultType:


-- This handler is called by other handlers
on makeURLFromFileOrPath:theFileOrPathInput
    -- make it into a Cocoa object for easier comparison
    set theFileOrPath to (NSArray's arrayWithObject:theFileOrPathInput)'s firstObject()
    if (theFileOrPath's isKindOfClass:(NSString)) as boolean then
        if (theFileOrPath's hasPrefix:"/") as boolean then -- full POSIX path
            return |NSURL|'s fileURLWithPath:theFileOrPath
        else if (theFileOrPath's hasPrefix:"~") as boolean then -- POSIX path needing ~ expansion
            return |NSURL|'s fileURLWithPath:(theFileOrPath's |stringByExpandingTildeInPath|())
        else -- must be HFS path
            return |NSURL|'s fileURLWithPath:(POSIX path of theFileOrPathInput)
        end if
    else if (theFileOrPath's isKindOfClass:(|NSURL|)) as boolean then -- happens with files and aliases in 10.11
        return theFileOrPath
    else -- must be a file or alias
        return |NSURL|'s fileURLWithPath:(POSIX path of theFileOrPathInput)
    end if
end makeURLFromFileOrPath:


-- This handler is called by other handlers
on filesAndPackagesInURLArray:theURLs
    set AsObjCTrue to current application's NSNumber's numberWithBool:true
    set itemURLs to NSMutableArray's array()
    repeat with aURL in theURLs -- is it a directory?
        set {theResult, theValue, theError} to (aURL's getResourceValue:(reference) forKey:NSURLIsDirectoryKey |error|:(reference))
        if theValue = AsObjCTrue then -- is it a package?
            set {theResult, theValue, theError} to (aURL's getResourceValue:(reference) forKey:NSURLIsPackageKey |error|:(reference))
            if theValue = AsObjCTrue then (itemURLs's addObject:aURL)
        else
            (itemURLs's addObject:aURL)
        end if
    end repeat
    return itemURLs
end filesAndPackagesInURLArray:


-- This handler is called by other handlers
on convertURLs:theURLs resultType:resType
    considering numeric strings
        if resType = "names" then
            return ((((theURLs's valueForKey:"lastPathComponent")'s componentsJoinedByString:(character id 0))'s stringByReplacingOccurrencesOfString:":" withString:"/")'s componentsSeparatedByString:(character id 0)) as list
        else if resType = "POSIX names" then
            return (theURLs's valueForKey:"lastPathComponent") as list
        else if resType = "urls" then
            return theURLs
        else if resType = "files" and AppleScript's version > "2.4" then
            return theURLs as list
        else
            return (theURLs's valueForKey:"path") as list
        end if
    end considering
end convertURLs:resultType:
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文