Отримання списку файлів у каталозі з глобусом


136

З якихось божевільних причин я не можу знайти спосіб отримати список файлів із глобулом для заданої директорії.

На даний момент я застряг у чомусь такому:

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

..і потім знімає речі, які я не хочу, що смокче. Але те, що мені дуже хотілося, - це мати можливість шукати щось на кшталт "foo * .jpg", а не просити весь каталог, але я нічого не зміг знайти.

То як, чорт, ти це робиш?


Відповідь Брайана Вебстера мені дуже допомогла у подібному питанні. stackoverflow.com/questions/5105250 / ...
Wytchkraft

1
Лише бічна примітка для кожного, хто читає це, ви зможете вирішити це, просто помістивши свої файли в папку stackoverflow.com/questions/1762836/…
seo

Відповіді:


240

Ви можете досягти цього досить легко за допомогою NSPredicate, наприклад:

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, це виглядає приблизно так:

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
ДиректоріяContentsAtPath застаріла з iOS 2.0. Це питання + відповідь занадто старий ...
Jonny

7
Просто продовжив і оновив зразок коду, щоб використовувати contentOfDirectoryAtPath: помилка: а не каталогContentsAtPath:
Brian Webster

5
Так, ви можете додати додаткову логіку за допомогою операцій АБО, наприклад, "self ENDSWITH '.jpg' OR self ENDSWITH '.png'"
Brian Webster

2
Це приголомшливо ... Я вже цілий день манюся з іншими підходами! Чудово. Основна хитрість - це просто знати, що шукати на StackO!
Кліф Рібаудо,

3
Ви можете використовувати "pathExtension == '.xxx'" замість "ENDSWITH". Подивіться цю відповідь
Бруно Беріссо

34

Це дуже добре працює IOS, але також має працювати 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

Що з використанням методів hasSuffix та hasPrefix NSString? Щось на зразок (якщо ви шукаєте "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

    }
}

Для простих, простих матчів, таких, як це було б простіше, ніж використання бібліотеки регулярних виразів.


Ви повинні використовувати contentsOfDirectoryAtPath:error:замість того, directoryContentsAtPathщо його deprecatedпочинаючи з iOS2.0
Алекс Ціо

Це перша відповідь в списку , щоб відповісти на цей питання, тому я голосував це
Гай

12

Дуже простий метод:

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 є бібліотека, яка може виконувати операції з глобалізації файлів для вас. Функції та типи оголошені в заголовку, який називається glob.h, тому вам знадобиться #include. Якщо ви відкриєте термінал, відкрийте сторінку man для глобального введення, man 3 globви отримаєте всю інформацію, яку вам потрібно знати, щоб користуватися функціями.

Нижче наводиться приклад того, як ви могли заповнити масив файлів, що відповідають шаблону глобалізації. Під час використання globфункції потрібно пам’ятати кілька речей.

  1. За замовчуванням globфункція шукає файли в поточному робочому каталозі. Для пошуку в іншому каталозі вам потрібно додати ім’я каталогу до шаблону глобалізації, як я це робив у своєму прикладі, щоб отримати всі файли /bin.
  2. Ви несете відповідальність за очищення виділеної пам'яті glob, зателефонувавши, globfreeколи закінчите зі структурою.

У своєму прикладі я використовую параметри за замовчуванням і не має зворотного виклику помилок. Сторінка "man" охоплює всі варіанти, якщо ви хочете використати щось там. Якщо ви збираєтесь використовувати вищевказаний код, я б запропонував додати його як категорію NSArrayабо щось подібне.

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

Редагувати: я створив суть на github, яка містить вищевказаний код у категорії під назвою NSArray + Globbing .


stringWithCString:застаріло. Правильна заміна є -[NSFileManager stringWithFileSystemRepresentation:length:], хоча я думаю, що більшість людей використовує stringWithUTF8String:(що простіше, але не гарантується правильним кодуванням).
Пітер Хосей

5

Для усунення файлів, які ви не хочете, потрібно прокрутити власний метод.

З вбудованими інструментами це непросто, але ви можете використовувати RegExKit Lite, щоб допомогти знайти елементи у поверненому масиві, який вас цікавить. Відповідно до приміток до випуску, це має працювати як у програмах Cocoa, так і Cocoa-Touch.

Ось демо-код, який я написав приблизно за 10 хвилин. Я змінив <і> на ", тому що вони не відображалися всередині попереднього блоку, але він все ще працює з цитатами. Можливо, хтось, хто знає більше про форматування коду тут на StackOverflow, виправить це (Chris?).

Це проект шаблону утиліти командного рядка "Інструмент фундаменту". Якщо на моєму домашньому сервері буде запущений демон git, я відредагую цю публікацію, щоб додати URL-адресу проекту.

#import "Фонд / Foundation.h"
#import "RegexKit / RegexKit.h"

@interface MTFileMatcher: NSObject 
{
}
- (недійсні) getFilesMatchingRegEx: (NSString *) inRegex forPath: (NSString *) inPath;
@end

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

    // тут вставити код ...
    MTFileMatcher * matcher = [[[MTFileMatcher alloc] init] автовипуск];
    [matcher getFilesMatchingRegEx: @ "^. + \\. [Jj] [Pp] [Ee]? [gg] $" forPath: [@ "~ / Pictures" stringByExpandingTildeInPath]];

    [злив у басейн];
    повернути 0;
}

@ реалізація MTFileMatcher
- (недійсні) getFilesMatchingRegEx: (NSString *) inRegex forPath: (NSString *) inPath;
{
    NSArray * filesAtPath = [[[[NSFileManager defaultManager] каталогContentsAtPath: inPath] arrayByMatchingObjectsWithRegex: inRegex];
    NSEnumerator * itr = [filesAtPath objectEnumerator];
    NSString * obj;
    while (obj = [itr nextObject])
    {
        NSLog (obj);
    }
}
@end

3

Я не буду претендувати на те, що я є експертом по цій темі, але ви повинні мати доступ і до функції, globі до wordexpфункції від Obje-c, ні?



0

Швидкий 5

Це працює на какао

        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

Швидкий 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  {  }
        }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.