web-dev-qa-db-fra.com

Obtenir une liste de fichiers dans un répertoire avec un glob

Pour une raison folle, je ne trouve pas le moyen d'obtenir une liste de fichiers avec un glob pour un répertoire donné.

Je suis actuellement coincé avec quelque chose du genre:

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

..et puis dépouillant ce que je ne veux pas, ce qui est nul. Mais ce que j'aimerais vraiment, c'est pouvoir chercher quelque chose comme "foo * .jpg" au lieu de demander tout le répertoire, mais je n'ai rien trouvé de tel.

Alors comment diable le faites-vous?

134
sammich

Vous pouvez y arriver assez facilement avec NSPredicate, comme ceci:

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];

Si vous avez besoin de le faire avec NSURL à la place, cela ressemble à ceci:

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];
239
Brian Webster

Cela fonctionne assez bien pour IOS, mais devrait aussi fonctionner pour 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);            
    }       
}
32
Matt

Qu'en est-il des méthodes hasSuffix et hasPrefix de NSString? Quelque chose comme (si vous recherchez "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

    }
}

Pour des correspondances simples et simples comme celle-ci, il serait plus simple d'utiliser une bibliothèque de regex.

27
John Biesnecker

Méthode la plus simple:

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);
12
Rajesh Loganathan

Unix a une bibliothèque qui peut effectuer des opérations de vidage de fichiers pour vous. Les fonctions et les types sont déclarés dans un en-tête appelé glob.h, vous aurez donc besoin de #include il. Si vous ouvrez un terminal, ouvrez la page de manuel de glob en tapant man 3 glob vous obtiendrez toutes les informations nécessaires pour utiliser les fonctions.

Vous trouverez ci-dessous un exemple de la manière dont vous pourriez remplir un tableau avec les fichiers correspondant à un modèle de remplacement. Lorsque vous utilisez la fonction glob, vous devez garder à l’esprit quelques points.

  1. Par défaut, la fonction glob recherche les fichiers du répertoire de travail en cours. Afin de rechercher un autre répertoire, vous devez ajouter le nom du répertoire au motif de remplacement tel que je l’ai fait dans mon exemple pour obtenir tous les fichiers au format /bin.
  2. Vous êtes responsable du nettoyage de la mémoire allouée par glob en appelant globfree lorsque vous avez terminé avec la structure.

Dans mon exemple, j'utilise les options par défaut et aucun rappel d'erreur. La page de manuel couvre toutes les options au cas où vous souhaiteriez utiliser quelque chose. Si vous envisagez d'utiliser le code ci-dessus, je suggérerais de l'ajouter en tant que catégorie à NSArray ou quelque chose du genre.

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: J'ai créé un gist sur github qui contient le code ci-dessus dans une catégorie appelée NSArray + Globbing .

10
Bryan Kyle

Vous devez utiliser votre propre méthode pour éliminer les fichiers que vous ne voulez pas.

Ce n'est pas facile avec les outils intégrés, mais vous pouvez utiliser RegExKit Lite pour vous aider à trouver les éléments dans le tableau retourné qui vous intéresse. Selon les notes de publication, cela devrait fonctionner à la fois dans Cocoa et les applications Cocoa-Touch.

Voici le code de démonstration que j'ai rédigé en 10 minutes environ. J'ai changé le <et> en "parce qu'ils n'apparaissaient pas à l'intérieur du bloc pré, mais cela fonctionne toujours avec les guillemets. Peut-être que quelqu'un qui en sait plus sur le code de formatage ici sur StackOverflow corrigera cela (Chris?).

Il s'agit d'un projet de modèle d'utilitaire de ligne de commande "Foundation Tool". Si mon démon git est opérationnel sur mon serveur domestique, je modifierai ce message pour ajouter l'URL du projet.

 # 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]; 
 
 // insérez du code ici ... 
 MTFileMatcher * matcher = [[[[MTFileMatcher alloc] init] relecture automatique]; 
 [Matcher getFilesMatchingRegEx: @ "^. + \\. [Jj] [Pp] [Ee]? E [Gg] $ "forPath: [@" ~/Pictures "stringByExpandingTildeInPath]]; 
 
 [drain de piscine]; 
 renvoyer 0; 
} 
 
 @ implementation MTFileMatcher 
 - (void) getFilesMatchingRegEx: (NSString *) inRegex pourPath: (NSString *) inPath; 
 {
 NSArray * filesAtPath = [[NSFileManager defaultManager] directoryContentsAtPath: inPath] arrayByMatchingObjectsWithRegex: inRegex]; 
 NSEnumerator * itr = [filesAtPath objectEnumerator]; 
 NSString * obj; 
 tant que (obj = [itr nextObject]) 
 {
 NSLog (obj); 
} 
}
@fin
5
Mark

Je ne prétends pas être un expert sur le sujet, mais vous devriez avoir accès à la fois à la fonction glob et wordexp de l'objectif-c, non?

3
Sean Bright

stringWithFileSystemRepresentation ne semble pas être disponible sous iOS.

2
Oscar