Buscador
A continuación se presentan algunas formas diferentes de filtrar por extensión de archivo, con una breve descripción de sus ventajas. A modo de ilustración, he puesto Buscador las operaciones realizadas sobre un Buscador ventana (mi Fotos ), que tiene muchos jpegs que sirven como una buena muestra con la que 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")
La segunda vez que se realizó, se tardó 14 segundos, con el fin de proporcionar una línea de base para las comparaciones aproximadas.
El simple hecho de coaccionar el resultado a un alias list
aceleró sistemáticamente el tiempo de ejecución 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)
Sorprendentemente para mí, filtrar por name extension
no parecía afectar a los tiempos de rendimiento en comparación con el uso del name
lo que podría sugerir que ambos realizan 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, yo elegiría preferentemente filtrar por name extension
como una cuestión de elección personal, porque es una sintaxis más limpia.
Una de las ventajas de Buscador es que podemos condensar varios filtros en una sola 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 igual de 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)
Filtrado por el name
no puede hacerse con múltiples extensiones de esta manera, por lo que debe hacerse con cláusulas separadas para cada extensión que se 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
Eventos del sistema está mucho más equipado para manejar el procesamiento y filtrado de archivos que Buscador Lo cual es algo contraintuitivo. También impide Buscador que se bloquea durante la operación.
No se puede utilizar una lista de predicados como se puede hacer con Buscador 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 lleve aproximadamente cero segundos hace que merezca la pena. Obsérvese aquí que he preguntado Eventos del sistema para devolver el path
a estos elementos, simplemente para poder pasar el resultado a Buscador y hacer que los seleccione como antes (así también se puede usar reveal
después de un Eventos del sistema llamada).
Objetivo-C
Si necesita buscar en carpetas enormes o en una lista anidada de carpetas, no tenga la tentación de utilizar El buscador entire contents
propiedad, o te hará llorar. Utilice AppleScriptObjC, que realiza búsquedas profundas en árboles de carpetas con tiempos de rendimiento más rápidos que Eventos del sistema y la cáscara. Tiene el coste de unos gastos generales ligeramente superiores a los de Eventos del sistema / Buscador pero probablemente sea comparable a la de llamar a un shell script.
En primer lugar, es mejor definir algunos manejadores 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
Entonces, 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 distingan entre mayúsculas y minúsculas, por lo que es prudente incluir las extensiones de los archivos a excluir tanto en mayúsculas como en 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 Fotos filtrando todos los jpegs para devolver una lista de 643 archivos anidados en ese directorio, y lo hizo en aproximadamente cero segundos . Tampoco Buscador ni Eventos del sistema puede coincidir con este tiempo ( Buscador no responde después de un tiempo, y haciendo una búsqueda profunda con Eventos del sistema requiere iterar manualmente a través de las carpetas hijas, y decidir cómo manejar la lista anidada que devuelve, pero lo hace en unos impresionantes 4 segundos). El intérprete de comandos es igual de rápido para este número de archivos, pero estoy bastante seguro de lo que he leído que Objective-C superará al intérprete de comandos find
para grandes volúmenes de archivos.
Verás que he comentado el Buscador 's reveal
comando: pedir Buscador para revelar 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 las rutas de los mismos, que pueden utilizarse para cualquier operación que se desee Buscador para realizar posteriormente sobre ellos.
Si, por alguna razón, necesita utilizar Buscador para realizar la búsqueda de archivos, siempre coacciona a alias list
para obtener beneficios de rendimiento y una clase de elemento que es universalmente mucho más fácil de manejar después.
Para estructuras de carpetas grandes o anidadas, utilice Objective-C.