AppleScript가 폴더 아래에 포함 된 가장 큰 파일을 깊이 검색 할 수 있습니까?


1

선택한 디렉토리에서 가장 큰 파일을 찾을 수있는 AppleScript (다른 폴더 안에 있더라도)를 만들고 화면에 전체 경로를 표시해야합니다.

이것은 내가 지금까지 가지고 있지만 작동하지 않습니다.

set theItem to quoted form of POSIX path of (choose folder)

set theSize to (do shell script "/usr/bin/mdls -name kMDItemFSSize -raw " & theItem)

on open f

set filePath to do shell script "dirname " & POSIX path of f as string

display dialog theFilePath

위의 스크립트에서 작동하지 않는 것을 말하는 방법을 잘 모르겠습니다. 이 작업을 수행하는 다음 단계를 도울 수 있습니까?

답변:


2

이 작업을 수행하는 방법에는 각각 장단점이있는 다양한 방법이 있습니다. 쉘 방법이 빠른있는 분에 , 하지만 항상 최신 정보를 반환하지 않습니다 . AppleScript의 Finder 인터페이스는 생각보다 느리지 않지만 캐시 된 파일 크기에 대해 실행 가능한 값만 반환하고 그렇지 않은 경우 나머지 값은 "missing value"를 반환합니다. 시스템 이벤트 는 일반적으로 검색시 빠르지 만 파일 속성에 액세스 할 때 속도가 느려지므로 선택한 AppleScript 파일 관리 응용 프로그램입니다. 또한 Finder 처럼 깊은 디렉토리 열거를 수행 할 수 없습니다 (수동으로 구현 할 수는 있지만).

Objective-C 스크립팅 브리지를 사용하여 매우 빠르며 디렉토리의 하위 폴더로 완전히 내려갈 수있는 AppleScript를 작성하기로 결정했습니다. 전반적으로 가장 좋은 방법이지만 선생님이 약간 의심 할 수 있다는 단점이 있습니다.

# Loads the Foundation framework into the script so that we can access its
# methods and constants
use framework "Foundation"

# Declare properties that belong to the Foundation framework for easier
# referencing within the script
property this : a reference to current application
property NSArray : a reference to NSArray of this
property NSDirectoryEnumerationSkipsHiddenFiles : a reference to 4
property NSDirectoryEnumerationSkipsPackageDescendants : a reference to 2
property NSFileManager : a reference to NSFileManager of this
property NSSortDescriptor : a reference to NSSortDescriptor of this
property NSString : a reference to NSString of this
property NSURL : a reference to NSURL of this
property NSURLFileSizeKey : a reference to NSURLFileSizeKey of this
property NSURLNameKey : a reference to NSURLNameKey of this
property NSURLPathKey : a reference to NSURLPathKey of this

# Call the handler defined below.  This is where the script does the actual
# retrieving of the files and filesizes
get my contentsOfDirectory:"~/Downloads"

# If we stopped the script at the line above, you'd see the entire contents of 
# the directory subtree listed with file paths and filesizes, ordered in 
# descending order by filesize.  However, you only want the largest file, so
# we pick out the first item in the list.
return item 1 of the result

--------------------------------------------------------------------------------
# This is an AppleScript handler declaration
on contentsOfDirectory:dir
    local dir # This tells the handler that the variable passed as the
    # parameter is limited in scope to this handler

    # Obtain a reference to the default file manager of the filesystem
    set FileManager to NSFileManager's defaultManager()

    # This is where retrieve the contents of the directory, recursing
    # into any subfolders.  The options declared tell the method to skip
    # hidden files and not to look inside file packages, such as 
    # applications or library files.  I've declared a list of keys that
    # pre-fetch file attributes during this retrieval, making it faster
    # to access their data later: filename, full path, and file size.
    set fs to FileManager's enumeratorAtURL:(NSURL's ¬
        fileURLWithPath:((NSString's stringWithString:dir)'s ¬
            stringByStandardizingPath())) ¬
        includingPropertiesForKeys:[¬
        NSURLPathKey, ¬
        NSURLNameKey, ¬
        NSURLFileSizeKey] ¬
        options:(NSDirectoryEnumerationSkipsHiddenFiles + ¬
        NSDirectoryEnumerationSkipsPackageDescendants) ¬
        errorHandler:(missing value)

    # I created the script object just to speed up the process of
    # appending new items to the empty list it contains.
    script |files|
        property list : {}
    end script

    # This is the repeat loop that we use to enumerate the contents
    # of the directory tree that we retrieved above
    repeat
        # This allows us to access each item in the enumerator one
        # by one.
        set f to fs's nextObject()

        # Once the list has been exhausted, the value returned above
        # will be a "missing value", signifying that there are no more
        # files to enumerate.  Therefore, we can exit the loop.
        if f = missing value then exit repeat

        # Here, we retrieve the values of file attributes denoted
        # by the keys I declared earlier.  I'm picking out the path
        # and the filesize as per your needs.
        f's resourceValuesForKeys:[NSURLPathKey, NSURLFileSizeKey] ¬
            |error|:(missing value)

        # The above command returns a record containing the two
        # file attributes.  This record gets appended to the list
        # stored in the script object above.
        set end of list of |files| to the result as record
    end repeat

    # The list in the script object is an AppleScript list object.  For
    # the next part, I need a cocoa list object (NSArray).
    set L to item 1 of (NSArray's arrayWithObject:(list of |files|))

    # This defines a sort descriptor which is used to sort the array.
    # I'm telling it to use the filesize key to sort the array by 
    # filesize, which will let us grab the largest file easily.
    set descriptor to NSSortDescriptor's alloc()'s ¬
        initWithKey:"NSURLFileSizeKey" ascending:no

    # Sort the list.
    L's sortedArrayUsingDescriptors:[descriptor]

    # Return the result.
    result as list
end contentsOfDirectory:

1

이것은 다른 답변에 사용 된 AppleScript Objective-C 코드 의 대안으로 제공되며 OP에 표시된 표준 AppleScript 코드 라인에 더 가깝습니다 . 이 답변에 대한 크레딧은 다른 답변 인 CJK의 저자에게 귀속됩니다. CJK는 원래 답변에서 서로 삭제 한 의견에서 파생 되었기 때문입니다. 또한 복잡함에도 불구하고 그의 대답은 여기에 제공된 것보다 성능이 우수하다고 생각합니다.

이 스크립트가 실행되면 사용자가 폴더를 선택하면 하위 폴더를 포함하여 선택한 폴더 내에서 가장 큰 파일 경로 이름이 대화 상자에 표시됩니다.

AppleScript 코드 예 :

set chosenFolder to quoted form of POSIX path of ¬
    (text items 1 thru -2 of ((choose folder) as text) as text)

set theLargestFilePathname to ¬
    (do shell script "find " & chosenFolder & ¬
        " -type f -ls | sort -nrk7 | awk '{for(i=11; i<=NF; ++i) printf $i\"\"FS; exit}'")

display dialog "The largest file within the chosen folder, and its subfolders, is:" & ¬
    linefeed & linefeed & theLargestFilePathname buttons {"OK"} default button 1 ¬
    -- giving up after 3        # Remove the '--' at the front of this line to enable this.

내 다운로드 폴더의 최종 결과는 아래와 같은 대화 상자입니다.

디스플레이 대화 상자

표시된 경로 파일 이름은 현재 디스크의 5.27GB에있는 다운로드 폴더에서 가장 큰 파일입니다.


참고 : 예제 AppleScript 코드 는 그저 코드 일 뿐이며 오류 처리가 포함되어 있지 않습니다. 사용자는 적절하거나 필요하거나 원하는 오류 처리를 추가해야합니다.


@ CJ, 귀하의 답변에서 삭제 된 의견에 부분적 으로이 답변을 추가했습니다.
user3439894

1
그리고 나는 그것이 +1 가치가 있다고 생각합니다.
CJK
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.