Получение списка файлов в каталоге с глобусом


136

По какой-то безумной причине я не могу найти способ получить список файлов с глобусом для данного каталога.

В настоящее время я застрял с чем-то вроде:

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

..и затем убираю вещи, которые я не хочу, и это отстой. Но что мне действительно нравится, так это возможность искать что-то вроде «foo * .jpg» вместо того, чтобы просить весь каталог, но я не смог найти ничего подобного.

Так как, черт возьми, ты это делаешь?


Ответ Брайана Вебстера очень помог мне в подобной проблеме. stackoverflow.com/questions/5105250/…
Wytchkraft

1
Просто примечание стороны к любому читает это, вы можете быть в состоянии решить эту проблему, просто положить файлы в папку stackoverflow.com/questions/1762836/...
сео

Ответы:


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
directoryContentsAtPath устарела, начиная с iOS 2.0. Этот вопрос + ответ слишком стар ...
Джонни

7
Просто пошли дальше и обновили пример кода, чтобы использовать contentsOfDirectoryAtPath: ошибка: вместо directoryContentsAtPath:
Брайан Вебстер

5
Да, вы можете добавить дополнительную логику, используя операторы OR, например, «self ENDSWITH» .jpg «ИЛИ self ENDSWITH '.png» »
Брайан Вебстер

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
Alex Cio

Это первый ответ в списке, чтобы ответить на вопрос, поэтому я проголосовал за него
Парень

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 3 globсправочную страницу для 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];

Изменить: я создал GIST на GitHub, который содержит приведенный выше код в категории под названием NSArray + Globbing .


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

5

Вы должны свернуть свой собственный метод, чтобы удалить файлы, которые вы не хотите.

Это не легко с помощью встроенных инструментов, но вы можете использовать RegExKit Lite, чтобы помочь найти элементы в возвращаемом массиве, который вас интересует. Согласно примечаниям к выпуску, это должно работать как в приложениях Cocoa, так и Cocoa-Touch.

Вот демонстрационный код, который я написал примерно за 10 минут. Я изменил <и> на ", потому что они не показывались внутри предварительного блока, но он все еще работает с кавычками. Возможно, кто-то, кто знает больше о форматировании кода здесь в StackOverflow, исправит это (Крис?).

Это шаблон проекта утилиты командной строки «Foundation Tool». Если я установлю и запустлю мой демон git на своем домашнем сервере, я отредактирую этот пост, добавив URL-адрес проекта.

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

@interface MTFileMatcher: NSObject 
{
}
- (void) getFilesMatchingRegEx: (NSString *) inRegex forPath: (NSString *) inPath;
@конец

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

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

    [сток бассейна];
    вернуть 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);
    }
}
@конец

3

Я не буду притворяться экспертом по этой теме, но у вас должен быть доступ к функциям globи wordexpфункциям из target-c, нет?



0

Swift 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

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  {  }
        }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.