Pobieranie listy plików w katalogu o nazwie glob

136

Z jakiegoś szalonego powodu nie mogę znaleźć sposobu na pobranie listy plików z globem dla danego katalogu.

Obecnie utknąłem z czymś w rodzaju:

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

.. a potem wyrzucanie rzeczy, których nie chcę, co jest do bani. Ale naprawdę chciałbym móc wyszukać coś takiego jak „foo * .jpg” zamiast pytać o cały katalog, ale nie udało mi się znaleźć czegoś takiego.

Więc jak do cholery to robisz?

sammich
źródło
Odpowiedź Briana Webstera bardzo mi pomogła w podobnej sprawie. stackoverflow.com/questions/5105250/…
Wytchkraft
1
Na marginesie dla każdego, kto to czyta, możesz rozwiązać ten problem, po prostu umieszczając swoje pliki w folderze stackoverflow.com/questions/1762836/ ...
seo

Odpowiedzi:

240

Możesz to łatwo osiągnąć za pomocą NSPredicate, na przykład:

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

Jeśli chcesz to zrobić za pomocą NSURL, wygląda to tak:

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
źródło
2
directoryContentsAtPath jest przestarzała od wersji iOS 2.0. To pytanie + odpowiedź są zbyt stare ...
Jonny
7
Po prostu poszedł do przodu i aktualizowane próbkę kodu do korzystania contentsOfDirectoryAtPath: błąd: zamiast directoryContentsAtPath:
Brian Webster
5
Tak, możesz dodać dodatkową logikę za pomocą instrukcji OR, np. „Self ENDSWITH '.jpg' OR self ENDSWITH '.png'"
Brian Webster
2
To jest niesamowite ... Przez cały dzień sikałem dookoła innymi podejściami! Wspaniały. Główną sztuczką jest po prostu wiedzieć, czego szukać w StackO!
Cliff Ribaudo
3
Możesz użyć „pathExtension == '.xxx'” zamiast „ENDSWITH”. Spójrz tę odpowiedź
Bruno Berisso
34

Działa to całkiem nieźle w przypadku IOS, ale powinno też działać w przypadku 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);            
    }       
}
Matt
źródło
28

A co z używaniem metod hasSuffix i hasPrefix firmy NSString? Coś takiego (jeśli szukasz „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

    }
}

W przypadku takich prostych, nieskomplikowanych dopasowań byłoby prostsze niż użycie biblioteki wyrażeń regularnych.

John Biesnecker
źródło
Powinieneś używać contentsOfDirectoryAtPath:error:zamiast, directoryContentsAtPathponieważ jest deprecatedod iOS2.0
Alex Cio,
To jest pierwsza odpowiedź na liście, która odpowiada na pytanie, więc zagłosowałem za nią
Guy
12

Najprostsza metoda:

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
źródło
10

Unix posiada bibliotekę, która może wykonywać za Ciebie operacje na plikach. Funkcje i typy są zadeklarowane w nagłówku o nazwie glob.h, więc będziesz go potrzebować #include. Jeśli otworzysz terminal i otworzysz stronę podręcznika dla glob, wpisując go man 3 glob, otrzymasz wszystkie informacje potrzebne do korzystania z funkcji.

Poniżej znajduje się przykład, jak można zapełnić tablicę plikami, które pasują do wzorca globbingu. Podczas korzystania z tej globfunkcji należy pamiętać o kilku rzeczach.

  1. Domyślnie globfunkcja szuka plików w bieżącym katalogu roboczym. Aby przeszukać inny katalog, musisz dołączyć nazwę katalogu do wzorca globowania, tak jak to zrobiłem w moim przykładzie, aby pobrać wszystkie pliki /bin.
  2. Jesteś odpowiedzialny za oczyszczenie przydzielonej pamięci globprzez wywołanie, globfreegdy skończysz ze strukturą.

W moim przykładzie używam domyślnych opcji i żadnego wywołania zwrotnego błędu. Strona podręcznika zawiera wszystkie opcje na wypadek, gdyby było tam coś, czego chcesz użyć. Jeśli zamierzasz użyć powyższego kodu, sugerowałbym dodanie go jako kategorii do NSArraylub czegoś podobnego.

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

Edycja: stworzyłem sedno na github, który zawiera powyższy kod w kategorii o nazwie NSArray + Globbing .

Bryan Kyle
źródło
stringWithCString:jest przestarzałe. Prawidłowy zamiennik to -[NSFileManager stringWithFileSystemRepresentation:length:], chociaż myślę, że większość ludzi używa stringWithUTF8String:(co jest łatwiejsze, ale nie gwarantuje, że będzie to właściwe kodowanie).
Peter Hosey
5

Musisz zastosować własną metodę, aby wyeliminować pliki, których nie chcesz.

Nie jest to łatwe z wbudowanymi narzędziami, ale możesz użyć RegExKit Lite do pomocy w znalezieniu interesujących Cię elementów w zwracanej tablicy. Zgodnie z uwagami do wydania powinno to działać zarówno w aplikacjach Cocoa, jak i Cocoa-Touch.

Oto kod demo, który napisałem w około 10 minut. Zmieniłem <i> na ", ponieważ nie pojawiały się one w bloku wstępnym, ale nadal działają z cudzysłowami. Może ktoś, kto wie więcej o formatowaniu kodu tutaj w StackOverflow, poprawi to (Chris?).

To jest projekt szablonu narzędzia wiersza poleceń „Foundation Tool”. Jeśli uruchomię demona git na serwerze domowym, edytuję ten post, aby dodać adres URL projektu.

#import "Fundacja / Fundacja.h"
#import „RegexKit / RegexKit.h”

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

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

    // wstaw kod tutaj ...
    MTFileMatcher * matcher = [[[MTFileMatcher alert] init] autorelease];
    [matcher getFilesMatchingRegEx: @ "^. + \\. [Jj] [Pp] [Ee]? [Gg] $" forPath: [@ "~ / Pictures" stringByExpandingTildeInPath]];

    [odpływ do basenu];
    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);
    }
}
@koniec
znak
źródło
3

Nie będę udawać, że jestem ekspertem w tej dziedzinie, ale powinieneś mieć dostęp zarówno do funkcji, jak globi wordexpod celu-c, nie?

Sean Bright
źródło
2

stringWithFileSystemRepresentation nie wydaje się być dostępny w systemie iOS.

Oscar
źródło
0

Szybki 5

To działa w przypadku kakao

        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)")
            }
        }
czarna Perła
źródło
0

Swift 5 na kakao

        // 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
źródło