Buscador
Aquí hay algunas formas diferentes de filtrar por extensión de archivo, con una breve descripción de sus beneficios. Para fines de ilustración, he tenido operaciones de Finder en una ventana abierta de Finder (mi carpeta Pictures ), que tiene muchos archivos JPEG en. Es una buena muestra contra la cual probar los filtros de exclusión.
tell application "Finder" to select (every file in the ¬
front Finder window whose name does not end with ".jpg")
Esto tomó 14 segundos en su segunda ejecución, para proporcionar una línea de base para comparaciones aproximadas.
El simple acto de coaccionar el resultado a un alias list
aceleró el tiempo de rendimiento a 8 segundos (casi el doble de rápido):
tell application "Finder" to select ((every file in the ¬
front Finder window whose name does not end with ".jpg") as alias list)
Para mí, sorprendentemente, el filtrado por name extension
no pareció afectar los tiempos de rendimiento en comparación con el uso de la propiedad name
, posiblemente sugiriendo que ambos están realizando comparaciones de cadenas equivalentes bajo el capó:
tell application "Finder" to select ((every file in the ¬
front Finder window whose name extension is not "jpg") as alias list)
No obstante, preferiría filtrar por name extension
como una cuestión personal, porque es una sintaxis más clara.
Uno de los beneficios de Finder es que podemos condensar múltiples filtros en una expresión inclusiva que esencialmente forma una lista de predicados:
tell application "Finder" to select ((every file in the ¬
front Finder window whose name extension is not in ¬
["jpg", "png"]) as alias list)
y esto fue tan rápido para dos extensiones que para una, y luego otra vez para cuatro:
tell application "Finder" to select ((every file in the ¬
front Finder window whose name extension is not in ¬
["jpg", "png", "mov", "mp4"]) as alias list)
El filtrado por la propiedad name
no se puede hacer con múltiples extensiones de esta manera, por lo que se debe hacer con cláusulas separadas para cada extensión que desee excluir:
tell application "Finder" to select ((every file in the front Finder window whose ¬
name does not end with "jpg" and ¬
name does not end with "png" and ¬
name does not end with "mp4" and ¬
name does not end with "mov") as alias list)
Eventos del sistema
System Events está mucho más equipado para manejar el procesamiento y filtrado de archivos que Finder , que es algo contraintuitivo. También evita que Finder se bloquee durante la operación.
No puedes usar una lista de predicados como puedes con Finder , así que tenemos que conformarnos con las expresiones más largas:
tell application "System Events" to get path of every file in the ¬
pictures folder whose visible = true and ¬
name extension is not "jpg" and ¬
name extension is not "png" and ¬
name extension is not "mp4" and ¬
name extension is not "mov"
tell application "Finder" to select the result
Pero el hecho de que esta operación tome aproximadamente cero segundos hace que valga la pena. Tenga en cuenta que le pedí a Eventos del sistema que devolviera path
a estos elementos, simplemente para poder pasar el resultado a Finder y hacer que los seleccione como antes (esto También es cómo puede usar reveal
después de una llamada de Eventos del sistema ).
Objective-C
Si necesitas buscar en carpetas grandes o en una lista anidada de carpetas, no te sientas tentado a usar la propiedad Finder's entire contents
, o te hará llorar. Use AppleScriptObjC, que realiza búsquedas profundas de árboles de carpetas con tiempos de rendimiento más rápidos que Eventos del sistema y shell. Tiene un costo de un poco más de sobrecarga en comparación con Eventos del sistema / Finder , pero probablemente comparable al de llamar a un script de shell.
Primero, es mejor definir algunos manejadores para que se encarguen de la búsqueda y el filtrado de archivos:
use framework "Foundation"
use scripting additions
property this : a reference to current application
property NSDirectoryEnumerationSkipsHiddenFiles : a reference to 4
property NSDirectoryEnumerationSkipsPackageDescendants : a reference to 2
property NSFileManager : a reference to NSFileManager of this
property NSMutableSet : a reference to NSMutableSet of this
property NSPredicate : a reference to NSPredicate of this
property NSSet : a reference to NSSet of this
property NSString : a reference to NSString of this
property NSURL : a reference to NSURL of this
on filesInDirectory:fp excludingExtensions:exts
local fp, exts
set all to contentsOfDirectory at fp
set |*fs| to all's filteredArrayUsingPredicate:(NSPredicate's ¬
predicateWithFormat:("pathExtension IN %@") ¬
argumentArray:[exts])
set fs to NSMutableSet's setWithArray:all
fs's minusSet:(NSSet's setWithArray:|*fs|)
fs's allObjects() as list
end filesInDirectory:excludingExtensions:
on contentsOfDirectory at fp
local fp
set FileManager to NSFileManager's defaultManager()
set fs to FileManager's enumeratorAtURL:(NSURL's ¬
fileURLWithPath:((NSString's stringWithString:fp)'s ¬
stringByStandardizingPath())) ¬
includingPropertiesForKeys:[] ¬
options:(NSDirectoryEnumerationSkipsHiddenFiles + ¬
NSDirectoryEnumerationSkipsPackageDescendants) ¬
errorHandler:(missing value)
fs's allObjects()
end contentsOfDirectory
Luego, puedes realizar una llamada como esta:
get my filesInDirectory:"~/Pictures" excludingExtensions:["jpg", "JPG", ""]
-- tell application "Finder" to reveal the result
Tenga en cuenta que Objective-C realizará búsquedas que distinguen entre mayúsculas y minúsculas, por lo que es prudente incluir las extensiones de archivo que se excluirán tanto en formato de mayúsculas como de minúsculas. La cadena vacía excluye las carpetas (excepto cuando el nombre de la carpeta contiene un punto).
Objective-C realizó una enumeración profunda de mi carpeta Imágenes filtrando todos los archivos JPEG para devolver una lista de 643 archivos anidados dentro de ese directorio, y lo hizo en aproximadamente cero segundos . Ni Finder ni System Events pueden coincidir esta vez ( Finder no responderá después de un tiempo, y realizar una búsqueda profunda con System Los eventos requieren una iteración manual a través de carpetas secundarias, y decidir cómo manejar la lista anidada que devuelve, pero lo hace en unos impresionantes 4 segundos. El shell es igual de rápido para este número de archivos, pero confío bastante en lo que he leído que Objective-C ejecutará el comando find
del shell para grandes volúmenes de archivos.
Verás. Comenté el comando reveal
del Finder : pedirle a Finder que revelara 643 archivos en diferentes carpetas fue ... um ... desagradable. No lo recomiendo.
Conclusión
① Utilice Eventos del sistema para realizar búsquedas de archivos y, opcionalmente, recuperar rutas de archivos, que pueden utilizarse para cualquier operación que desee que Finder realice posteriormente sobre ellas.
② Si, por alguna razón, necesita usar Finder para realizar la búsqueda de archivos, siempre coaccione con alias list
para obtener beneficios de rendimiento y una clase de elemento eso es mucho más fácil de manejar más tarde.
③ Para estructuras de carpetas grandes o anidadas, use Objective-C.