Abrufen einer Liste von Dateien in einem Verzeichnis mit einem Glob

136

Aus irgendeinem verrückten Grund kann ich keine Möglichkeit finden, eine Liste von Dateien mit einem Glob für ein bestimmtes Verzeichnis zu erhalten.

Ich bin derzeit mit etwas in der Art festgefahren wie:

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

..und dann das Zeug ausziehen, das ich nicht will, was scheiße ist. Aber was ich wirklich möchte, ist, nach etwas wie "foo * .jpg" suchen zu können, anstatt nach dem gesamten Verzeichnis zu fragen, aber ich konnte so etwas nicht finden.

Also, wie zum Teufel machst du das?

sammich
quelle
Die Antwort von Brian Webster hat mir in einem ähnlichen Thema sehr geholfen. stackoverflow.com/questions/5105250/…
Wytchkraft
1
Nur eine Randnotiz für jeden, der dies liest, Sie können dies möglicherweise lösen, indem Sie Ihre Dateien einfach in einen Ordner stapeln. Stackoverflow.com/questions/1762836/…
seo

Antworten:

240

Sie können dies ziemlich einfach mit Hilfe von NSPredicate erreichen, wie folgt:

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

Wenn Sie es stattdessen mit NSURL tun müssen, sieht es so aus:

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
quelle
2
directoryContentsAtPath ist seit iOS 2.0 veraltet. Diese Frage + Antwort sind zu alt ...
Jonny
7
Ich habe gerade das Codebeispiel aktualisiert, um contentOfDirectoryAtPath: error: anstelle von directoryContentsAtPath zu verwenden:
Brian Webster
5
Ja, Sie können zusätzliche Logik mithilfe von OR-Anweisungen hinzufügen, z. B. "self ENDSWITH '.jpg' OR self ENDSWITH '.png'"
Brian Webster,
2
Das ist großartig ... Ich habe jetzt einen ganzen Tag mit anderen Ansätzen herumgepisst! Toll. Der Haupttrick besteht darin, zu wissen, wonach bei StackO gesucht werden muss!
Cliff Ribaudo
3
Sie können die "pathExtension == '.xxx'" anstelle von "ENDSWITH" verwenden. Schauen Sie diese Antwort
Bruno Berisso
34

Das funktioniert ganz gut für IOS, sollte aber auch funktionieren 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
quelle
28

Was ist mit der Verwendung der hasSuffix- und hasPrefix-Methoden von NSString? So etwas wie (wenn Sie nach "foo * .jpg" suchen):

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

    }
}

Für einfache, unkomplizierte Übereinstimmungen wie diese wäre es einfacher als die Verwendung einer Regex-Bibliothek.

John Biesnecker
quelle
Sie sollten contentsOfDirectoryAtPath:error:anstelle von verwenden, directoryContentsAtPathweil es deprecatedseit iOS2.0 ist
Alex Cio
Dies ist die erste Antwort in der Liste, die die Frage beantwortet, also habe ich abgestimmt
Guy
12

Sehr einfachste Methode:

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
quelle
10

Unix verfügt über eine Bibliothek, die Datei-Globbing-Vorgänge für Sie ausführen kann. Die Funktionen und Typen werden in einem Header deklariert genannt glob.h, so dass Sie brauchen #includees. Wenn Sie ein Terminal öffnen und die Manpage für glob durch Eingabe öffnen, man 3 globerhalten Sie alle Informationen, die Sie zur Verwendung der Funktionen benötigen.

Im Folgenden finden Sie ein Beispiel dafür, wie Sie ein Array mit Dateien füllen können, die einem Globbing-Muster entsprechen. Wenn Sie die globFunktion verwenden, müssen Sie einige Dinge beachten.

  1. Standardmäßig globsucht die Funktion nach Dateien im aktuellen Arbeitsverzeichnis. Um ein anderes Verzeichnis zu durchsuchen, müssen Sie den Verzeichnisnamen wie in meinem Beispiel dem Globbing-Muster voranstellen, um alle Dateien abzurufen /bin.
  2. Sie sind dafür verantwortlich, den zugewiesenen Speicher zu bereinigen glob, globfreeindem Sie aufrufen, wenn Sie mit der Struktur fertig sind.

In meinem Beispiel verwende ich die Standardoptionen und keinen Fehlerrückruf. Die Manpage enthält alle Optionen für den Fall, dass Sie etwas verwenden möchten. Wenn Sie den obigen Code verwenden möchten, würde ich vorschlagen, ihn als Kategorie NSArrayoder ähnliches hinzuzufügen .

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

Bearbeiten: Ich habe einen Kern auf Github erstellt, der den obigen Code in einer Kategorie namens NSArray + Globbing enthält .

Bryan Kyle
quelle
stringWithCString:ist veraltet. Der richtige Ersatz ist -[NSFileManager stringWithFileSystemRepresentation:length:], obwohl ich denke, dass die meisten Leute verwenden stringWithUTF8String:(was einfacher ist, aber nicht garantiert die richtige Codierung ist).
Peter Hosey
5

Sie müssen Ihre eigene Methode rollen, um die Dateien zu entfernen, die Sie nicht möchten.

Dies ist mit den integrierten Tools nicht einfach, aber Sie können RegExKit Lite verwenden , um die Elemente in dem zurückgegebenen Array zu finden, an dem Sie interessiert sind. Gemäß den sollte dies sowohl in Cocoa- als auch in Cocoa-Touch-Anwendungen funktionieren.

Hier ist der Demo-Code, den ich in ungefähr 10 Minuten geschrieben habe. Ich habe das <und> in "geändert, weil sie nicht im Vorblock angezeigt wurden, aber es funktioniert immer noch mit den Anführungszeichen. Vielleicht korrigiert dies jemand, der mehr über das Formatieren von Code hier auf StackOverflow weiß (Chris?).

Dies ist ein Vorlagenprojekt für das Befehlszeilenprogramm "Foundation Tool". Wenn ich meinen Git-Daemon auf meinem Heimserver zum Laufen bringe, bearbeite ich diesen Beitrag, um die URL für das Projekt hinzuzufügen.

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

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

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

    // Code hier einfügen ...
    MTFileMatcher * matcher = [[[MTFileMatcher-Zuweisung] init] Autorelease];
    [matcher getFilesMatchingRegEx: @ "^. + \\. [Jj] [Pp] [Ee]? [Gg] $" forPath: [@ "~ / Pictures" stringByExpandingTildeInPath]];

    [Poolablauf];
    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);
    }}
}}
@Ende
Kennzeichen
quelle
3

Ich werde nicht vorgeben, ein Experte für das Thema zu sein, aber Sie sollten Zugriff auf sowohl die globals auch die wordexpFunktion von Ziel-C haben, nicht wahr?

Sean Bright
quelle
2

stringWithFileSystemRepresentation scheint in iOS nicht verfügbar zu sein.

Oscar
quelle
0

Swift 5

Dies funktioniert für 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)")
            }
        }
schwarze Perle
quelle
0

Swift 5 für 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
quelle