AppleScript può ottenere il contenuto della cartella con l'esclusione dell'estensione del file?

2

Alla ricerca di un modo in AppleScript per ottenere il contenuto di una directory con un'esclusione da analizzare. So come farlo usando find in un ciclo for con il comando:

find . -not -name "*.bat"

ma sono curioso di sapere se esiste un approccio AppleScript per ottenere il contenuto di una cartella senza l'estensione del file .bat .

Ho creato una directory fittizia sul desktop, ho aggiunto diversi file e ho provato:

tell application "Finder"
    set theFiles to get every item of (entire contents of folder (choose folder)) whose kind ≠ ".bat"
    reveal theFiles
end tell

i file .bat sono evidenziati. Usando does not contain compila, ma errori in:

Errore:

Can’t get every item of true.

Codice:

tell application "Finder"
    set theFiles to get every item of (entire contents of folder (choose folder) does not contain ".bat")
    reveal theFiles
end tell

Provando un altro approccio ottengo un errore di:

Errore:

Finder got an error: Unknown object type.

Codice:

tell application "Finder"
    set theFiles to get every item of (entire contents of folder (choose folder)) whose type ≠ {"public.bat"}
    reveal theFiles
end tell

Se provo a modificare l'approccio, posso ottenere un risultato valido solo se si restringe il nome di un file bat utilizzando:

Codice:

tell application "Finder"
    set theFiles to get (every file of folder (choose folder) whose name is not in {"foobar.bat"})
    reveal theFiles
end tell

In puro AppleScript c'è un modo per ottenere il contenuto di una directory con un'esclusione per il tipo di file? Mi piacerebbe associare l'esclusione per più tipi di file.

    
posta ʀ2ᴅ2 15.11.2018 - 19:43
fonte

2 risposte

2

Prova questo:

tell application "Finder"
    set theFiles to files in folder (choose folder) whose name does not end with ".bat"
    reveal theFiles
end tell
    
risposta data 15.11.2018 - 23:04
fonte
1

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 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.

    
risposta data 16.11.2018 - 21:31
fonte

Leggi altre domande sui tag