1 votos

¿Puede AppleScript buscar en profundidad el archivo más grande contenido en una carpeta?

Necesito hacer un AppleScript que encuentre el archivo más grande en el directorio seleccionado (incluso si está dentro de otra carpeta) y muestre la ruta completa en la pantalla.

Esto es lo que tengo hasta ahora, pero no funciona:

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

No estoy seguro de cómo decir lo que no está funcionando desde el script anterior. Puedes ayudarme con el siguiente paso para que esto funcione?

2voto

qarma Puntos 71

Hay varios métodos para llevar a cabo esta tarea, cada uno con pros y contras. Los métodos de cáscara son rápidos ish , pero no siempre devuelven información actualizada . El sistema de AppleScript Buscador La interfaz no es tan lenta como pensé que sería, pero sólo devuelve valores viables para los tamaños de archivo que han sido almacenados en la caché, de lo contrario "valor perdido" para el resto. Eventos del sistema es normalmente la aplicación de gestión de archivos de AppleScript de elección, ya que es rápido en la recuperación, pero se ralentiza al acceder a los atributos del archivo. Tampoco puede hacer una enumeración profunda de directorios como Buscador puede (aunque se puede implementar uno manualmente).

Decidí utilizar el puente de scripting de Objective-C para escribir un AppleScript que es a la vez súper rápido y totalmente capaz de descender a las subcarpetas de un directorio. En general, es el mejor método, pero viene con el inconveniente de que su profesor podría ser un poco sospechoso.

# 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:

1voto

user3439894 Puntos 5883

Esto se ofrece como una alternativa a la AppleScript Objetivo-C código utilizado en la otra respuesta y está más en la línea de la estándar AppleScript código que se muestra en el PO. Nótese que el mérito de esta respuesta es del autor de la otra respuesta, CJK, ya que se deriva de los comentarios ahora borrados que nos hicimos mutuamente bajo su respuesta original. Además, considero que su respuesta, a pesar de la complejidad, es superior en rendimiento a la que se ofrece aquí.

Cuando este script se ejecuta, el usuario elige una carpeta y el resultado final, el nombre de ruta de los archivos más grandes dentro de la carpeta elegida, incluyendo sus subcarpetas, se muestra en un cuadro de diálogo.

Ejemplo AppleScript código :

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.

El resultado final en mi carpeta de descargas es el cuadro de diálogo que se muestra a continuación:

display dialog box

El nombre de archivo de la ruta que se muestra es, en este momento, el archivo más grande de mi carpeta de descargas, con 5,27 GB en el disco.


Nota: El ejemplo AppleScript código es sólo eso y no contiene ningún manejo de errores como puede ser apropiado. Es responsabilidad del usuario añadir cualquier gestión de errores que pueda ser apropiada, necesaria o deseada.

0 votos

@CJK, he añadido esta respuesta basándome en parte en los comentarios ya borrados de tu respuesta.

1 votos

Y creo que merece un +1.

AppleAyuda.com

AppleAyuda es una comunidad de usuarios de los productos de Apple en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X