Mendapatkan daftar file dalam direktori dengan glob


136

Untuk beberapa alasan gila, saya tidak dapat menemukan cara untuk mendapatkan daftar file dengan glob untuk direktori tertentu.

Saat ini saya terjebak dengan sesuatu di sepanjang baris:

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

..dan kemudian menghapus hal-hal yang tidak saya inginkan, yang menyebalkan. Tetapi yang benar-benar saya inginkan adalah dapat mencari sesuatu seperti "foo * .jpg" daripada menanyakan seluruh direktori, tetapi saya tidak dapat menemukan yang seperti itu.

Jadi, bagaimana Anda melakukannya?


Jawaban Brian Webster banyak membantu saya dalam masalah serupa. stackoverflow.com/questions/5105250/…
Wytchkraft

1
Sekadar catatan bagi siapa pun yang membaca ini, Anda mungkin dapat menyelesaikannya hanya dengan meletakkan file Anda ke dalam folder stackoverflow.com/questions/1762836/…
seo

Jawaban:


240

Anda dapat mencapai ini dengan cukup mudah dengan bantuan NSPredicate, seperti:

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

Jika Anda perlu melakukannya dengan NSURL, tampilannya akan seperti ini:

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 tidak digunakan lagi sejak iOS 2.0. Pertanyaan + jawaban ini terlalu tua ...
Jonny

7
Lanjutkan saja dan perbarui contoh kode untuk menggunakan contentOfDirectoryAtPath: error: daripada directoryContentsAtPath:
Brian Webster

5
Ya, Anda dapat menambahkan logika tambahan menggunakan pernyataan OR, misalnya "self ENDSWITH '.jpg' OR self ENDSWITH '.png'"
Brian Webster

2
Ini luar biasa ... Saya telah bermain-main dengan pendekatan lain selama sehari penuh sekarang! Bagus. Trik utamanya adalah mengetahui apa yang harus dicari di StackO!
Cliff Ribaudo

3
Anda dapat menggunakan "pathExtension == '.xxx'" sebagai ganti "ENDSWITH". Lihat jawaban
Bruno Berisso

34

Ini bekerja cukup baik untuk IOS, tetapi juga bekerja untuk 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);            
    }       
}

28

Bagaimana dengan menggunakan metode hasSuffix dan hasPrefix NSString? Sesuatu seperti (jika Anda menelusuri "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

    }
}

Untuk pencocokan sederhana dan langsung seperti itu, ini akan lebih sederhana daripada menggunakan pustaka regex.


Anda harus menggunakan contentsOfDirectoryAtPath:error:bukan directoryContentsAtPathkarena deprecatedsejak iOS2.0
Alex Cio

Ini adalah jawaban pertama dalam daftar untuk menjawab pertanyaan, jadi saya memilihnya
Guy

12

Metode Sangat Sederhana:

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

10

Unix memiliki pustaka yang dapat melakukan operasi penggabungan file untuk Anda. Fungsi dan tipe dideklarasikan dalam sebuah header yang dipanggil glob.h, jadi Anda akan membutuhkannya #include. Jika membuka terminal, buka halaman manual untuk glob dengan mengetik, man 3 globAnda akan mendapatkan semua informasi yang perlu Anda ketahui untuk menggunakan fungsi.

Di bawah ini adalah contoh bagaimana Anda bisa mengisi array file yang cocok dengan pola globbing. Saat menggunakan globfungsi ini, ada beberapa hal yang perlu Anda ingat.

  1. Secara default, globfungsi mencari file di direktori kerja saat ini. Untuk mencari direktori lain, Anda harus menambahkan nama direktori ke pola globbing seperti yang telah saya lakukan dalam contoh saya untuk memasukkan semua file /bin.
  2. Anda bertanggung jawab untuk membersihkan memori yang dialokasikan globdengan menelepon globfreesetelah Anda selesai dengan strukturnya.

Dalam contoh saya, saya menggunakan opsi default dan tidak ada kesalahan panggilan balik. Halaman manual mencakup semua opsi jika ada sesuatu di sana yang ingin Anda gunakan. Jika Anda akan menggunakan kode di atas, saya sarankan menambahkannya sebagai kategori NSArrayatau sesuatu seperti itu.

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

Sunting: Saya telah membuat intisari pada github yang berisi kode di atas dalam kategori yang disebut NSArray + Globbing .


stringWithCString:sudah ditinggalkan. Pengganti yang benar adalah -[NSFileManager stringWithFileSystemRepresentation:length:], meskipun menurut saya kebanyakan orang menggunakan stringWithUTF8String:(yang lebih mudah tetapi tidak dijamin menjadi pengkodean yang benar).
Peter Hosey

5

Anda perlu menggulung metode Anda sendiri untuk menghilangkan file yang tidak Anda inginkan.

Ini tidak mudah dengan alat bawaan , tetapi Anda dapat menggunakan RegExKit Lite untuk membantu menemukan elemen dalam larik yang dikembalikan yang Anda minati. Menurut catatan rilis, ini seharusnya berfungsi baik di aplikasi Cocoa dan Cocoa-Touch.

Berikut kode demo yang saya tulis dalam waktu sekitar 10 menit. Saya mengubah <dan> menjadi "karena mereka tidak muncul di dalam blok awal, tetapi masih bekerja dengan tanda kutip. Mungkin seseorang yang tahu lebih banyak tentang kode format di StackOverflow akan memperbaiki ini (Chris?).

Ini adalah proyek template Utilitas Baris Perintah "Alat Dasar". Jika saya mendapatkan daemon git saya dan berjalan di server rumah saya, saya akan mengedit posting ini untuk menambahkan URL untuk proyek tersebut.

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

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

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

    // masukkan kode di sini ...
    MTFileMatcher * matcher = [[[MTFileMatcher alokasi] init] autorelease];
    [pencocokan getFilesMatchingRegEx: @ "^. + \\. [Jj] [Pp] [Ee]? [Gg] $" forPath: [@ "~ / Pictures" stringByExpandingTildeInPath]];

    [drainase kolam];
    kembali 0;
}

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

3

Saya tidak akan berpura-pura menjadi ahli dalam topik tersebut, tetapi Anda harus memiliki akses ke fungsi globdan wordexpdari tujuan-c, bukan?


2

stringWithFileSystemRepresentation tampaknya tidak tersedia di iOS.


0

Cepat 5

Ini bekerja untuk 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)")
            }
        }

0

Swift 5 untuk cocoa

        // 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  {  }
        }
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.