2009-01-31 7 views
131

Per qualche strano motivo non riesco a trovare un modo per ottenere un elenco di file con un glob per una determinata directory.Ottenere un elenco di file in una directory con un glob

Attualmente sto bloccato con qualcosa sulla falsariga di:

NSString *bundleRoot = [[NSBundle mainBundle] bundlePath]; 
NSArray *dirContents = [[NSFileManager defaultManager] 
         directoryContentsAtPath:bundleRoot]; 

..e quindi escludendo le cose che non voglio, che fa schifo. Ma quello che mi piacerebbe davvero è essere in grado di cercare qualcosa come "foo * .jpg" invece di chiedere l'intera directory, ma non sono stato in grado di trovare nulla di simile.

Quindi come diavolo lo fai?

+0

Brian Webster mi ha aiutato molto in un problema simile. http://stackoverflow.com/questions/5105250/run-nsbundle-from-the-documents-folder/7179584#7179584 – Wytchkraft

+1

Solo una nota a parte per chiunque stia leggendo questo, potresti riuscire a risolvere questo problema semplicemente mettendo i tuoi file in un cartella http://stackoverflow.com/questions/1762836/create-a-folder-inside-documents-folder-in-ios-apps – seo

risposta

3

Non farò finta di essere un esperto sull'argomento, ma dovresti avere accesso sia alla funzione glob e wordexp dall'obiettivo-c, no?

5

È necessario eseguire il rollover del proprio metodo per eliminare i file che non si desidera.

Questo non è facile con gli strumenti integrati, ma è possibile utilizzare RegExKit Lite per aiutare a trovare gli elementi nell'array restituito a cui si è interessati. Secondo le note di rilascio questo dovrebbe funzionare sia in Cocoa che in Cocoa-Touch applicazioni.

Ecco il codice demo che ho scritto in circa 10 minuti. Ho cambiato il < e> in "perché non erano visibili nel pre blocco, ma funziona ancora con le virgolette. Forse qualcuno che ne sa di più sulla formattazione del codice qui su StackOverflow correggerà questo (Chris?).

si tratta di un modello di progetto di comando Utility Line "Fondazione Tool". Se ottengo il mio git daemon installato e funzionante sul mio server casalingo io modificare questo post per aggiungere l'URL per il progetto.

 
#import "Foundation/Foundation.h" 
#import "RegexKit/RegexKit.h" 

@interface MTFileMatcher : NSObject 
{ 
} 
- (void)getFilesMatchingRegEx:(NSString*)inRegex forPath:(NSString*)inPath; 
@end 

int main (int argc, const char * argv[]) 
{ 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    // insert code here... 
    MTFileMatcher* matcher = [[[MTFileMatcher alloc] init] autorelease]; 
    [matcher getFilesMatchingRegEx:@"^.+\\.[Jj][Pp][Ee]?[Gg]$" forPath:[@"~/Pictures" stringByExpandingTildeInPath]]; 

    [pool drain]; 
    return 0; 
} 

@implementation MTFileMatcher 
- (void)getFilesMatchingRegEx:(NSString*)inRegex forPath:(NSString*)inPath; 
{ 
    NSArray* filesAtPath = [[[NSFileManager defaultManager] directoryContentsAtPath:inPath] arrayByMatchingObjectsWithRegex:inRegex]; 
    NSEnumerator* itr = [filesAtPath objectEnumerator]; 
    NSString* obj; 
    while (obj = [itr nextObject]) 
    { 
     NSLog(obj); 
    } 
} 
@end 
27

che dire usando i metodi hasSuffix e hasPrefix di NSString? Qualcosa di simile (se stai cercando "foo * .jpg"):

NSString *bundleRoot = [[NSBundle mainBundle] bundlePath]; 
NSArray *dirContents = [[NSFileManager defaultManager] directoryContentsAtPath:bundleRoot]; 
for (NSString *tString in dirContents) { 
    if ([tString hasPrefix:@"foo"] && [tString hasSuffix:@".jpg"]) { 

     // do stuff 

    } 
} 

Per corrispondenze semplici e intuitive come quella sarebbe più semplice dell'utilizzo di una libreria regex.

+0

Si dovrebbe usare 'contentsOfDirectoryAtPath: errore:' invece di 'directoryContentsAtPath' perché la sua' deprecated' dal momento che 'iOS' 2.0 –

+0

Questa è la prima risposta nell'elenco per rispondere alla domanda, quindi l'ho votata in su – Guy

236

È possibile raggiungere questo abbastanza facilmente con l'aiuto di NSPredicate, in questo modo:

NSString *bundleRoot = [[NSBundle mainBundle] bundlePath]; 
NSFileManager *fm = [NSFileManager defaultManager]; 
NSArray *dirContents = [fm contentsOfDirectoryAtPath:bundleRoot error:nil]; 
NSPredicate *fltr = [NSPredicate predicateWithFormat:@"self ENDSWITH '.jpg'"]; 
NSArray *onlyJPGs = [dirContents filteredArrayUsingPredicate:fltr]; 

Se avete bisogno di farlo con NSURL invece sembra che questo:

NSURL *bundleRoot = [[NSBundle mainBundle] bundleURL]; 
NSArray * dirContents = 
     [fm contentsOfDirectoryAtURL:bundleRoot 
     includingPropertiesForKeys:@[] 
          options:NSDirectoryEnumerationSkipsHiddenFiles 
          error:nil]; 
NSPredicate * fltr = [NSPredicate predicateWithFormat:@"pathExtension='jpg'"]; 
NSArray * onlyJPGs = [dirContents filteredArrayUsingPredicate:fltr]; 
+2

directoryContentsAtPath è obsoleto da iOS 2.0. Questa domanda + risposta sono troppo vecchie ... – Jonny

+7

Basta andare avanti e aggiornato l'esempio di codice per utilizzare contentsOfDirectoryAtPath: errore: piuttosto che directoryContentsAtPath: –

+0

questo sembra fantastico! c'è un modo per formattare il predicato per catturare due tipi di file contemporaneamente, come ".jpg" e ".png"? – mtmurdock

10

Unix ha un libreria che può eseguire operazioni di globbing dei file per te. Le funzioni e i tipi sono dichiarati in un'intestazione chiamata glob.h, quindi sarà necessario #include. Se apri un terminale apri la pagina man di glob digitando man 3 glob otterrai tutte le informazioni che ti servono per utilizzare le funzioni.

Di seguito è riportato un esempio di come è possibile popolare un array per i file che corrispondono a uno schema di globbing. Quando si utilizza la funzione glob ci sono alcune cose che è necessario tenere a mente.

  1. Per impostazione predefinita, la funzione glob cerca i file nella directory di lavoro corrente.Per cercare in un'altra directory è necessario anteporre il nome della directory allo schema di globbing come ho fatto nel mio esempio per ottenere tutti i file in /bin.
  2. Tu sei responsabile della pulizia della memoria allocata da glob chiamando globfree quando hai finito con la struttura.

Nel mio esempio utilizzo le opzioni predefinite e nessun errore di callback. La pagina man copre tutte le opzioni nel caso in cui ci sia qualcosa che vuoi usare. Se hai intenzione di utilizzare il codice sopra, suggerirei di aggiungerlo come categoria a NSArray o qualcosa del genere.

NSMutableArray* files = [NSMutableArray array]; 
glob_t gt; 
char* pattern = "/bin/*"; 
if (glob(pattern, 0, NULL, &gt) == 0) { 
    int i; 
    for (i=0; i<gt.gl_matchc; i++) { 
     [files addObject: [NSString stringWithCString: gt.gl_pathv[i]]]; 
    } 
} 
globfree(&gt); 
return [NSArray arrayWithArray: files]; 

Edit: ho creato un succo su GitHub che contiene il codice di cui sopra in una categoria chiamata NSArray+Globbing.

+0

'stringWithCString:' è deprecato. La sostituzione corretta è '- [NSFileManager stringWithFileSystemRepresentation: length:]', anche se penso che molte persone usino 'stringWithUTF8String:' (che è più facile ma non è garantito che sia la codifica corretta). –

+0

@Peter Grazie per il suggerimento. –

2

stringWithFileSystemRepresentation non sembra essere disponibile in iOS.

32

Questo funziona abbastanza bene per IOS, ma dovrebbe funzionare anche per cocoa.

NSString *bundleRoot = [[NSBundle mainBundle] bundlePath]; 
NSFileManager *manager = [NSFileManager defaultManager]; 
NSDirectoryEnumerator *direnum = [manager enumeratorAtPath:bundleRoot]; 
NSString *filename; 

while ((filename = [direnum nextObject])) { 

    //change the suffix to what you are looking for 
    if ([filename hasSuffix:@".data"]) { 

     // Do work here 
     NSLog(@"Files in resource folder: %@", filename);    
    }  
} 
12

Molto più semplice metodo: la risposta di

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, 
                NSUserDomainMask, YES); 
NSString *documentsDirectory = [paths objectAtIndex:0]; 

NSFileManager *manager = [NSFileManager defaultManager]; 
NSArray *fileList = [manager contentsOfDirectoryAtPath:documentsDirectory 
               error:nil]; 
//--- Listing file by name sort 
NSLog(@"\n File list %@",fileList); 

//---- Sorting files by extension  
NSArray *filePathsArray = 
    [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:documentsDirectory 
                 error:nil]; 
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF EndsWith '.png'"]; 
filePathsArray = [filePathsArray filteredArrayUsingPredicate:predicate]; 
NSLog(@"\n\n Sorted files by extension %@",filePathsArray); 
Problemi correlati