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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/499673/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 15:35:45  来源:igfitidea点击:

Getting a list of files in a directory with a glob

iosobjective-ciphonecocoacocoa-touch

提问by sammich

For some crazy reason I can't find a way to get a list of files with a glob for a given directory.

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

I'm currently stuck with something along the lines of:

我目前被困在以下方面:

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

..and then stripping out the stuff I don't want, which sucks. But what I'd really like is to be able to search for something like "foo*.jpg" instead of asking for the entire directory, but I've not been able to find anything like that.

..然后去掉我不想要的东西,这很糟糕。但我真正想要的是能够搜索诸如“foo*.jpg”之类的内容,而不是请求整个目录,但我找不到类似的内容。

So how the heck do you do it?

那么你到底是怎么做到的呢?

回答by Brian Webster

You can achieve this pretty easily with the help of NSPredicate, like so:

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

If you need to do it with NSURL instead it looks like this:

如果你需要用 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];

回答by Matt

This works quite nicely for IOS, but should also work for cocoa.

这对 非常有效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);            
    }       
}

回答by John Biesnecker

What about using NSString's hasSuffix and hasPrefix methods? Something like (if you're searching for "foo*.jpg"):

使用 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

    }
}

For simple, straightforward matches like that it would be simpler than using a regex library.

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

回答by Rajesh Loganathan

Very Simplest Method:

非常简单的方法:

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

回答by Bryan Kyle

Unix has a library that can perform file globbing operations for you. The functions and types are declared in a header called glob.h, so you'll need to #includeit. If open up a terminal an open the man page for glob by typing man 3 globyou'll get all of the information you need to know to use the functions.

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

Below is an example of how you could populate an array the files that match a globbing pattern. When using the globfunction there are a few things you need to keep in mind.

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

  1. By default, the globfunction looks for files in the current working directory. In order to search another directory you'll need to prepend the directory name to the globbing pattern as I've done in my example to get all of the files in /bin.
  2. You are responsible for cleaning up the memory allocated by globby calling globfreewhen you're done with the structure.
  1. 默认情况下,该glob函数在当前工作目录中查找文件。为了搜索另一个目录,您需要将目录名称添加到通配符模式之前,就像我在示例中所做的那样,以获取/bin.
  2. 您负责在完成结构后glob通过调用来清理分配的内存globfree

In my example I use the default options and no error callback. The man page covers all of the options in case there's something in there you want to use. If you're going to use the above code, I'd suggest adding it as a category to NSArrayor something like that.

在我的示例中,我使用默认选项并且没有错误回调。手册页涵盖了所有选项,以防您想使用其中的某些内容。如果您打算使用上面的代码,我建议将其添加为一个类别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];

Edit: I've created a gist on github that contains the above code in a category called NSArray+Globbing.

编辑:我在 github 上创建了一个要点,其中包含名为NSArray+Globbing的类别中的上述代码。

回答by Mark

You need to roll your own method to eliminate the files you don't want.

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

This isn't easy with the built in tools, but you could use RegExKit Liteto assist with finding the elements in the returned array you are interested in. According to the release notes this should work in both Cocoa and Cocoa-Touch applications.

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

Here's the demo code I wrote up in about 10 minutes. I changed the < and > to " because they weren't showing up inside the pre block, but it still works with the quotes. Maybe somebody who knows more about formatting code here on StackOverflow will correct this (Chris?).

这是我在大约 10 分钟内编写的演示代码。我将 < 和 > 更改为 " 因为它们没有出现在 pre 块中,但它仍然适用于引号。也许在 StackOverflow 上了解更多关于格式化代码的人会更正这个(克里斯?)。

This is a "Foundation Tool" Command Line Utility template project. If I get my git daemon up and running on my home server I'll edit this post to add the URL for the project.

这是一个“基础工具”命令行实用程序模板项目。如果我在我的家庭服务器上启动并运行我的 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

回答by Sean Bright

I won't pretend to be an expert on the topic, but you should have access to both the globand wordexpfunction from objective-c, no?

我不会假装是该主题的专家,但您应该可以访问Objective-c 中的globwordexp函数,不是吗?

回答by Oscar

stringWithFileSystemRepresentation doesn't appear to be available in iOS.

stringWithFileSystemRepresentation 在 iOS 中似乎不可用。

回答by black_pearl

Swift 5

斯威夫特 5

This works for cocoa

这适用于可可

        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)")
            }
        }

回答by dengST30

Swift 5for cocoa

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  {  }
        }