Glob ile bir dizindeki dosyaların listesini alma


136

Bazı çılgın nedenlerden dolayı, belirli bir dizin için bir glob ile dosyaların listesini almanın bir yolunu bulamıyorum.

Şu anda şu çizgilerle bir şey sıkışmış:

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

..ve sonra istemediğim şeyleri soyup berbat. Ama gerçekten istediğim, dizinin tamamını sormak yerine "foo * .jpg" gibi bir şey arayabilmektir, ancak böyle bir şey bulamadım.

Peki bunu nasıl yapıyorsun?


Brian Webster'ın yanıtı da benzer bir konuda bana çok yardımcı oldu. stackoverflow.com/questions/5105250/…
Wytchkraft

1
Bunu okuyan herkese sadece yan not, dosyalarınızı sadece bir klasöre koyarak bu sorunu çözebilirsiniz stackoverflow.com/questions/1762836/…
seo

Yanıtlar:


240

Bunu NSPredicate'in yardımıyla kolayca başarabilirsiniz, şöyle:

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

NSURL ile yapmanız gerekiyorsa bunun yerine şöyle görünür:

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, iOS 2.0'dan beri kullanımdan kaldırıldı. Bu soru + cevap çok eski ...
Jonny

7
Sadece devam etti ve contentOfDirectoryAtPath kullanmak için kod örneğini güncelledik: error: yerine directoryContentsAtPath:
Brian Webster

5
Evet, VEYA ifadelerini kullanarak ek mantık ekleyebilirsiniz, örn. "Self ENDSWITH '.jpg' VEYA self ENDSWITH '.png'"
Brian Webster

2
Bu harika ... Bir gün boyunca diğer yaklaşımlarla öfkeleniyorum! Harika. Ana hile sadece StackO'da ne arayacağını bilmek!
Cliff Ribaudo

3
"ENDSWITH" yerine "pathExtension == '.xxx'" kullanabilirsiniz. Bu cevaba
Bruno Berisso

34

Bu oldukça iyi çalışıyor IOS, ama aynı zamanda işe yaramalı 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

NSString'in hasSuffix ve hasPrefix yöntemlerini kullanmaya ne dersiniz? Şuna benzer ("foo * .jpg" araması yapıyorsanız):

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

    }
}

Bunun gibi basit, anlaşılır eşleşmeler için normal ifade kitaplığı kullanmaktan daha kolay olurdu.


Bunun contentsOfDirectoryAtPath:error:yerine kullanmalısınız directoryContentsAtPathçünkü 2.0'dan deprecatedberiiOS
Alex Cio

Bu, listeye soruyu cevaplayan ilk yanıt, bu yüzden oy verdim
Guy

12

En Basit Yöntem:

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, sizin için dosya globbing işlemleri yapabilen bir kütüphaneye sahiptir. İşlevler ve türler adlı bir başlıkta bildirildiğinden, buna glob.hihtiyacınız olacak #include. Bir terminal açarsanız ve glob için man sayfasını yazarak man 3 glob, işlevleri kullanmak için bilmeniz gereken tüm bilgileri alırsınız.

Aşağıda, bir globbing deseniyle eşleşen dosyaları bir diziye nasıl yerleştirebileceğinize ilişkin bir örnek verilmiştir. globİşlevi kullanırken aklınızda bulundurmanız gereken birkaç şey vardır.

  1. Varsayılan olarak, globişlev geçerli çalışma dizinindeki dosyaları arar. Başka bir dizini aramak için, tüm dosyaları almak için örneğimde yaptığım gibi dizin adını globbing desenine eklemeniz gerekir /bin.
  2. Yapı ile işiniz bittiğinde globarayarak ayrılan belleği temizlemek sizin sorumluluğunuzdadır globfree.

Örneğimde varsayılan seçenekleri kullanıyorum ve hata geri çağırma yok. Man sayfası, orada kullanmak istediğiniz bir şey olması durumunda tüm seçenekleri kapsar. Yukarıdaki kodu kullanacaksanız, bunu bir kategori NSArrayveya buna benzer bir şey olarak eklemenizi öneririm .

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

Düzenleme: NSArray + Globbing adlı kategoride yukarıdaki kodu içeren github üzerinde bir özü oluşturdum .


stringWithCString:kullanımdan kaldırıldı. -[NSFileManager stringWithFileSystemRepresentation:length:]Çoğu insanın kullandığını düşünmeme rağmen doğru değiştirme stringWithUTF8String:(daha kolay ancak doğru kodlama olduğu garanti edilmez).
Peter Hosey

5

İstemediğiniz dosyaları ortadan kaldırmak için kendi yönteminizi uygulamanız gerekir.

Yerleşik araçlarla bu kolay değildir, ancak ilgilendiğiniz iade dizisindeki öğeleri bulmanıza yardımcı olması için RegExKit Lite'ı kullanabilirsiniz . Sürüm notlarına göre bu hem Kakao hem de Kakao-Touch uygulamalarında çalışmalıdır.

İşte yaklaşık 10 dakika içinde yazdığım demo kodu. <Ve> olarak değiştirdim, çünkü ön blok içinde görünmüyorlardı, ama hala tırnak işaretleri ile çalışıyor. Belki StackOverflow'da kod biçimlendirme hakkında daha fazla bilgi sahibi olan biri bunu düzeltir (Chris?).

Bu bir "Temel Aracı" Komut Satırı Yardımcı Programı şablon projesidir. Git arka plan programımı çalıştırır ve ana sunucumda çalıştırırsam, projenin URL'sini eklemek için bu yayını düzenlerim.

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

@interface MTFileMatcher: NSObject 
{
}
- (geçersiz) getFilesMatchingRegEx: (NSString *) inRegex forPath: (NSString *) inPath;
@son

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

    // buraya kod girin ...
    MTFileMatcher * matcher = [[[MTFileMatcher ayırma] init] otomatik çalıştırma];
    [matcher getFilesMatchingRegEx: @ "^. + \\. [Jj] [Pp] [Ee]? [Gg] $" forPath: [@ "~ / Resimler" stringByExpandingTildeInPath]];

    [havuz tahliyesi];
    dönüş 0;
}

@implementation MTFileMatcher
- (geçersiz) getFilesMatchingRegEx: (NSString *) inRegex forPath: (NSString *) inPath;
{
    NSArray * filesAtPath = [[[[NSFileManager defaultManager] directoryContentsAtPath: inPath] diziByMatchingObjectsWithRegex: inRegex];
    NSEnumerator * itr = [filesAtPath objectEnumerator];
    NSString * obj;
    while (obj = [itr nextObject])
    {
        NSLog (obj);
    }
}
@son

3

Ben konuyla ilgili bir uzman taklit olmaz, ancak her iki erişimi olmalıdır globve wordexphiçbir objektif-c fonksiyonu?


2

stringWithFileSystemRepresentation, iOS'ta mevcut görünmüyor.


0

Hızlı 5

Bu kakao için çalışır

        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

Kakao için Swift 5

        // 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  {  }
        }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.