使用glob获取目录中的文件列表

时间:2009-01-31 22:08:21

标签: ios objective-c iphone cocoa cocoa-touch

由于某些疯狂的原因,我无法找到一种方法来获取给定目录的带有glob的文件列表。

我目前仍然坚持使用以下内容:

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

..然后剥掉我不想要的东西,这很糟糕。但我真正喜欢的是能够搜索“foo * .jpg”之类的东西,而不是要求整个目录,但是我找不到那样的东西。

那你该怎么做?

10 个答案:

答案 0 :(得分:238)

你可以在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];

答案 1 :(得分:32)

这适用于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);            
    }       
}

答案 2 :(得分:27)

使用NSString的hasSuffix和hasPrefix方法怎么样?类似的东西(如果你正在搜索“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

    }
}

对于简单,直接的匹配,它比使用正则表达式库更简单。

答案 3 :(得分: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);

答案 4 :(得分:10)

Unix有一个可以为你执行文件通配操作的库。函数和类型在名为glob.h的标头中声明,因此您需要#include它。如果打开一个终端,通过输入man 3 glob打开glob的手册页,您将获得使用这些功能所需的所有信息。

下面是一个示例,说明如何在数组中填充与globbing模式匹配的文件。使用glob功能时,您需要记住一些事项。

  1. 默认情况下,glob函数会查找当前工作目录中的文件。为了搜索另一个目录,您需要将目录名称添加到globbing模式中,就像我在我的示例中所做的那样,以获取/bin中的所有文件。
  2. 当您完成结构后,您有责任通过调用glob来清理globfree分配的内存。
  3. 在我的示例中,我使用默认选项,没有错误回调。手册页涵盖了所有选项,以防您想要使用其中的某些内容。如果您要使用上述代码,我建议将其作为类别添加到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的类别中的上述代码。

答案 5 :(得分:5)

您需要使用自己的方法来消除不需要的文件。

使用内置工具并不容易,但您可以使用RegExKit Lite来帮助查找您感兴趣的返回数组中的元素。根据发行说明,这应该适用于Cocoa和Cocoa-Touch应用程序。

这是我在大约10分钟内编写的演示代码。我改变了&lt;和&gt;为了“因为它们没有出现在前块中,但它仍然适用于引号。也许在StackOverflow上有更多关于格式化代码的人会纠正这个(Chris?)。

这是一个“基础工具”命令行实用程序模板项目。如果我在我的家庭服务器上启动并运行我的git守护程序,我将编辑此帖子以添加项目的URL。

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

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

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

    // insert code here...
    MTFileMatcher* matcher = [[[MTFileMatcher alloc] init] autorelease];
    [matcher getFilesMatchingRegEx:@"^.+\\.[Jj][Pp][Ee]?[Gg]$" forPath:[@"~/Pictures" stringByExpandingTildeInPath]];

    [pool drain];
    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);
    }
}
@end

答案 6 :(得分:3)

我不会假装成为该主题的专家,但你应该可以访问来自objective-c的globwordexp函数,不是吗?

答案 7 :(得分:2)

stringWithFileSystemRepresentation似乎在iOS中不可用。

答案 8 :(得分: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)")
            }
        }

答案 9 :(得分: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  {  }
        }