Finder
Ecco alcuni modi diversi di filtrare per estensione di file, con una breve descrizione dei loro benefici. A scopo illustrativo, ho avuto Finder operazioni eseguite su una finestra aperta Finder (la mia cartella Immagini ), che ha molti jpeg in è un buon esempio per testare i filtri di esclusione.
tell application "Finder" to select (every file in the ¬
front Finder window whose name does not end with ".jpg")
Ci sono voluti 14 secondi alla sua seconda esecuzione, per fornire una base per confronti grezzi.
L'unico semplice atto di forzare il risultato a alias list
ha costantemente velocizzato il tempo di esecuzione a 8 secondi (quasi il doppio della velocità):
tell application "Finder" to select ((every file in the ¬
front Finder window whose name does not end with ".jpg") as alias list)
Sorprendentemente, il filtraggio di name extension
non sembra influire sui tempi di esecuzione rispetto all'uso della proprietà name
, suggerendo che entrambi stiano eseguendo confronti di stringhe equivalenti sotto il cofano:
tell application "Finder" to select ((every file in the ¬
front Finder window whose name extension is not "jpg") as alias list)
Tuttavia preferirei scegliere di filtrare per name extension
come una questione di scelta personale, perché è una sintassi più pulita.
Uno dei vantaggi di Finder è che possiamo condensare più filtri in un'unica espressione inclusiva che essenzialmente forma un elenco di predicati:
tell application "Finder" to select ((every file in the ¬
front Finder window whose name extension is not in ¬
["jpg", "png"]) as alias list)
e questo è stato altrettanto veloce per due estensioni di quanto non fosse per una, e poi ancora per quattro:
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)
Il filtraggio della proprietà name
non può essere eseguito con più estensioni in questo modo, quindi deve essere fatto con clausole separate per ogni estensione che desideri escludere:
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)
Eventi di sistema
Eventi di sistema è molto più attrezzato per gestire l'elaborazione e il filtraggio dei file rispetto a Finder , il che è alquanto controintuitivo. Impedisce inoltre che Finder venga bloccato durante l'operazione.
Non puoi utilizzare un elenco di predicati come puoi con Finder , quindi dobbiamo accontentarci delle espressioni più lunghe:
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
Ma il fatto che questa operazione richieda circa zero secondi lo rende utile. Nota qui che ho chiesto a Eventi di sistema di restituire path
a questi elementi, semplicemente così potevo quindi passare il risultato a Finder e selezionarlo come prima (questo è anche possibile utilizzare reveal
dopo una chiamata Eventi di sistema .
Objective-C
Se hai bisogno di cercare enormi cartelle o un elenco annidato di cartelle, non essere tentato di usare la proprietà Finder entire contents
, altrimenti ti farà piangere. Usa AppleScriptObjC, che esegue ricerche approfondite di alberi di cartelle con tempi di esecuzione più veloci di Eventi di sistema e shell. Ha un costo leggermente superiore rispetto a Eventi di sistema / Finder , ma probabilmente è paragonabile a quello di chiamare uno script di shell.
Per prima cosa, è meglio definire alcuni gestori che si occupino della ricerca e del filtraggio dei file:
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
Quindi, puoi effettuare una chiamata in questo modo:
get my filesInDirectory:"~/Pictures" excludingExtensions:["jpg", "JPG", ""]
-- tell application "Finder" to reveal the result
Si noti che Objective-C eseguirà ricerche con distinzione tra maiuscole e minuscole, quindi è prudente includere estensioni di file da escludere nei formati maiuscolo e minuscolo. La stringa vuota esclude le cartelle (tranne quando il nome della cartella contiene un punto).
Objective-C ha eseguito una profonda enumerazione della mia cartella Immagini filtrando tutti i file jpeg per restituire un elenco di 643 file nidificati all'interno di quella directory, e lo ha fatto in circa zero secondi . Né Finder né Eventi di sistema possono abbinare questa volta ( Finder non risponderà dopo un po ', e facendo una ricerca approfondita con Sistema Gli eventi richiedono l'iterazione manuale delle cartelle figlio e decidono come gestire l'elenco annidato che restituisce, ma lo fa in ben 4 secondi). La shell è altrettanto veloce per questo numero di file, ma sono abbastanza fiducioso da quello che ho letto che Objective-C eseguirà il comando find
della shell per grandi volumi di file.
Vedrai che ho commentato il comando% em_de% di Finder : chiedere a Finder di rivelare 643 file in diverse cartelle è stato ... um ... sgradevole. Non lo consiglio.
Conclusione
① Utilizza Eventi di sistema per eseguire ricerche di file e facoltativamente recuperare percorsi di file, che possono essere utilizzati per qualsiasi operazione che desideri Finder per eseguire successivamente su di essi.
② Se lo fai, per qualche motivo, devi usare Finder per eseguire la ricerca di file, forzare sempre a reveal
per i vantaggi in termini di prestazioni e una classe di articoli questo è universalmente molto più facile da gestire in seguito.
③ Per strutture di cartelle grandi o nidificate, utilizzare Objective-C.