获取一个目录中的文件列表

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

我现在遇到了这样的问题:

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

..然后把我不想要的东西拿出来,真是糟透了。但是我真正想要的是能够搜索像“ foo *”这样的东西。而不是要求整个目录,但我还没有能够找到任何类似的东西。

你到底是怎么做到的?

107140 次浏览

我不会假装自己是这方面的专家,但是您应该可以从 Objective-c 访问 globwordexp函数,不是吗?

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

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

这是我在10分钟内写好的演示代码。我将 < and > 更改为“ ,因为它们没有显示在 pre 块中,但是它仍然可以使用引号。也许在 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

使用 NSString 的 hasAffix 和 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


}
}

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

您可以在 NSPreate 的帮助下非常容易地实现这一点,如下所示:

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

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

下面是一个示例,说明如何填充与 globbing 模式匹配的文件的数组。当使用 glob函数时,有一些事情你需要记住。

  1. 默认情况下,glob函数查找当前工作目录中的文件。为了搜索另一个目录,您需要在 globbing 模式前面添加目录名,就像我在示例中所做的那样,以获取 /bin中的所有文件。
  2. 在结构处理完成后,通过调用 globfree负责清理由 glob分配的内存。

在我的示例中,我使用默认选项,没有错误回调。手册页涵盖了所有选项,以防您想要使用其中的某些内容。如果你打算使用上面的代码,我建议将它作为一个类别添加到 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 上创建了一个 gist,它包含上面的代码,属于一个名为 NSArray + Globbing的类别。

StringWithFileSystemReform 在 iOS 中似乎不可用。

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

最简单的方法:

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

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

对于可可来说,雨燕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  {  }
}