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

136

Pour une raison folle, je ne trouve pas de 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épouiller les trucs que je ne veux pas, ce qui est nul. Mais ce que j'aimerais vraiment, c'est pouvoir rechercher quelque chose comme "foo * .jpg" au lieu de demander le répertoire entier, mais je n'ai rien trouvé de tel.

Alors comment diable faites-vous cela?

sammich
la source
La réponse de Brian Webster m'a beaucoup aidé dans un problème similaire. stackoverflow.com/questions/5105250/…
Wytchkraft
1
Juste une note à tous ceux qui liront ceci, vous pourrez peut-être résoudre ce problème en plaçant simplement vos fichiers dans un dossier stackoverflow.com/questions/1762836/…
seo

Réponses:

240

Vous pouvez y parvenir assez facilement avec l'aide de 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 devez 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];
Brian Webster
la source
2
directoryContentsAtPath est obsolète depuis iOS 2.0. Cette question + réponse sont trop anciennes ...
Jonny
7
Je viens de mettre à jour l'exemple de code pour utiliser contentsOfDirectoryAtPath: erreur: plutôt que directoryContentsAtPath:
Brian Webster
5
Ouais, vous pouvez ajouter une logique supplémentaire en utilisant des instructions OR, par exemple "self ENDSWITH '.jpg' OR self ENDSWITH '.png'"
Brian Webster
2
C'est génial ... Je pisse avec d'autres approches depuis une journée entière maintenant! Génial. L'astuce principale est simplement de savoir quoi rechercher sur StackO!
Cliff Ribaudo
3
Vous pouvez utiliser "pathExtension == '.xxx'" au lieu de "ENDSWITH". Regardez cette réponse
Bruno Berisso
34

Cela fonctionne très bien pour IOS, mais devrait également 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);            
    }       
}
Mat
la source
28

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 directes comme celle-ci, ce serait plus simple que d'utiliser une bibliothèque de regex.

John Biesnecker
la source
Vous devriez utiliser contentsOfDirectoryAtPath:error:au lieu de directoryContentsAtPathparce que c'est deprecateddepuis iOS2.0
Alex Cio
C'est la première réponse de la liste pour répondre à la question, alors je l'ai votée
Guy
12

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);
SVM-RAJESH
la source
10

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

Vous trouverez ci-dessous un exemple de la façon dont vous pouvez remplir un tableau des fichiers qui correspondent à un modèle de globbing. Lorsque vous utilisez la globfonction, vous devez garder à l'esprit certaines choses.

  1. Par défaut, la globfonction recherche les fichiers dans le répertoire de travail actuel. Pour rechercher un autre répertoire, vous devrez ajouter le nom du répertoire au modèle de globbing comme je l'ai fait dans mon exemple pour obtenir tous les fichiers /bin.
  2. Vous êtes responsable du nettoyage de la mémoire allouée globen appelant globfreelorsque 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 allez utiliser le code ci-dessus, je vous suggère de l'ajouter en tant que catégorie à NSArrayou 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 résumé sur github qui contient le code ci-dessus dans une catégorie appelée NSArray + Globbing .

Bryan Kyle
la source
stringWithCString:est obsolète. Le remplacement correct est -[NSFileManager stringWithFileSystemRepresentation:length:], bien que je pense que la plupart des gens utilisent stringWithUTF8String:(ce qui est plus facile mais pas garanti d'être le bon encodage).
Peter Hosey
5

Vous devez utiliser votre propre méthode pour éliminer les fichiers dont 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 du tableau renvoyé qui vous intéressent. Selon les notes de publication, cela devrait fonctionner dans les applications Cocoa et Cocoa-Touch.

Voici le code de démonstration que j'ai rédigé en 10 minutes environ. J'ai changé les <et> en "parce qu'ils n'apparaissaient pas dans le bloc pré, mais cela fonctionne toujours avec les guillemets. Peut-être que quelqu'un qui en sait plus sur le formatage du code 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 "Fondation / Fondation.h"
#import "RegexKit / RegexKit.h"

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

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

    // insérer le code ici ...
    MTFileMatcher * matcher = [[[MTFileMatcher alloc] init] autorelease];
    [correspondance getFilesMatchingRegEx: @ "^. + \\. [Jj] [Pp] [Ee]? [Gg] $" forPath: [@ "~ / Pictures" stringByExpandingTildeInPath]];

    [drain de piscine];
    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);
    }
}
@fin
marque
la source
3

Je ne prétendrai pas être un expert sur le sujet, mais vous devriez avoir accès à la fois à la fonction globet à wordexppartir d'objectif-c, non?

Sean Bright
la source
2

stringWithFileSystemRepresentation ne semble pas être disponible dans iOS.

oscar
la source
0

Swift 5

Cela fonctionne pour le cacao

        let bundleRoot = Bundle.main.bundlePath
        let manager = FileManager.default
        let dirEnum = manager.enumerator(atPath: bundleRoot)


        while let filename = dirEnum?.nextObject() as? String {
            if filename.hasSuffix(".data"){
                print("Files in resource folder: \(filename)")
            }
        }
perle noire
la source
0

Swift 5 pour le cacao

        // Getting the Contents of a Directory in a Single Batch Operation

        let bundleRoot = Bundle.main.bundlePath
        let url = URL(string: bundleRoot)
        let properties: [URLResourceKey] = [ URLResourceKey.localizedNameKey, URLResourceKey.creationDateKey, URLResourceKey.localizedTypeDescriptionKey]
        if let src = url{
            do {
                let paths = try FileManager.default.contentsOfDirectory(at: src, includingPropertiesForKeys: properties, options: [])

                for p in paths {
                     if p.hasSuffix(".data"){
                           print("File Path is: \(p)")
                     }
                }

            } catch  {  }
        }
dengST30
la source