迭代遍历文件夹中的文件与嵌套文件夹- Cocoa



我需要访问文件夹中的每个文件,包括存在于嵌套文件夹中的文件。一个示例文件夹可能如下所示:

animals/
 -k.txt
 -d.jpg
 cat/
   -r.txt
   -z.jpg
   tiger/
      -a.jpg
      -p.pdf
 dog/
   -n.txt
   -f.jpg
 -p.pdf

假设我想在"animals"文件夹下的每个文件上运行一个进程。遍历文件夹"animals"及其所有子文件夹以访问每个文件的最佳方法是什么?

谢谢。

使用NSDirectoryEnumerator递归枚举您想要的目录下的文件和目录,并要求它告诉您它是文件还是目录。以下是基于-[NSFileManager enumeratorAtURL:includingPropertiesForKeys:options:errorHandler:]文档中列出的示例:

NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *directoryURL = … // URL pointing to the directory you want to browse
NSArray *keys = [NSArray arrayWithObject:NSURLIsDirectoryKey];
NSDirectoryEnumerator *enumerator = [fileManager
    enumeratorAtURL:directoryURL
    includingPropertiesForKeys:keys
    options:0
    errorHandler:^BOOL(NSURL *url, NSError *error) {
        // Handle the error.
        // Return YES if the enumeration should continue after the error.
        return YES;
}];
for (NSURL *url in enumerator) { 
    NSError *error;
    NSNumber *isDirectory = nil;
    if (! [url getResourceValue:&isDirectory forKey:NSURLIsDirectoryKey error:&error]) {
        // handle error
    }
    else if (! [isDirectory boolValue]) {
        // No error and it’s not a directory; do something with the file
    }
}

也许你可以这样写:

+(void)openEachFileAt:(NSString*)path
{
  NSDirectoryEnumerator* enumerator = [[NSFileManager defaultManager] enumeratorAtPath:path];
  for (NSString * file in enumerator)
  {
     // check if it's a directory
     BOOL isDirectory = NO;
    NSString* fullPath = [path stringByAppendingPathComponent:file];
    [[NSFileManager defaultManager] fileExistsAtPath:fullPath
                                         isDirectory: &isDirectory];
    if (!isDirectory)
    {
      // open your file (fullPath)…
    }
    else
    {
      [self openEachFileAt: fullPath];
    }
  }
}

简写如下:

func openEachFile(inDirectory path: String) {
    let subs = try! FileManager.default.subpathsOfDirectory(atPath: path)
    let totalFiles = subs.count
    print(totalFiles)
    for sub in subs {
        if sub.hasSuffix(".DS_Store") {
            //a DS_Store file
        }
        else if sub.hasSuffix(".xcassets") {
            //a xcassets file
        }
        else if (sub as NSString).substring(to: 4) == ".git" {
            //a git file
        }
        else if sub.hasSuffix(".swift") {
            //a swift file
        }
        else if sub.hasSuffix(".m") {
            //a objc file
        }
        else if sub.hasSuffix(".h") {
            //a header file
        }
        else {
            // some other file
        }
        let fullPath = (path as NSString).appendingPathComponent(sub)
    }
}

这是一个使用-subpathsOfDirectoryAtPath:rootPath的解决方案,带有文件url和现代Objective-C可空性钟&功能。

typedef void (^FileEnumerationBlock)(NSURL *_Nonnull fileURL);
@interface NSFileManager (Extensions)
- (void)enumerateWithRootDirectoryURL:(nonnull NSURL *)rootURL
                          fileHandler:(FileEnumerationBlock _Nonnull)fileHandler
                                error:(NSError *_Nullable *_Nullable)error;
@end
@implementation NSFileManager (Extensions)
- (void)enumerateWithRootDirectoryURL:(NSURL *)rootURL
                          fileHandler:(FileEnumerationBlock)fileHandler
                                error:(NSError **)error {
    NSString *rootPath = rootURL.path;
    NSAssert(rootPath != nil, @"Invalid root URL %@ (nil path)", rootURL);
    NSArray *subs = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:rootPath
                                                                        error:error];
    if (!subs) {
        return;
    }
    for (NSString *sub in subs) {
        fileHandler([rootURL URLByAppendingPathComponent:sub]);
    }
}
@end

…在Swift中也是如此:

func enumerate(rootDirectoryURL rootURL: NSURL, fileHandler:(URL:NSURL)->Void) throws {
    guard let rootPath = rootURL.path else {
        preconditionFailure("Invalid root URL: (rootURL)")
    }
    let subs = try NSFileManager.defaultManager().subpathsOfDirectoryAtPath(rootPath)
    for sub in subs {
        fileHandler(URL: rootURL.URLByAppendingPathComponent(sub))
    }
}

这段代码对我有效

NSMutableString *allHash;  
  -(NSString*)getIterate:(NSString*)path {
        allHash = [NSMutableString stringWithString:@""];
        NSDirectoryEnumerator *de= [[NSFileManager defaultManager] enumeratorAtPath:path];
        NSString *file;
        BOOL isDirectory;
        for(file in de)
        {
            //first check if it's a file
            NSString* fullPath = [NSString stringWithFormat:@"%@/%@",path,file];
            BOOL fileExistsAtPath = [[NSFileManager defaultManager] fileExistsAtPath:fullPath isDirectory:&isDirectory];
            NSLog(@"Check=>%d",fileExistsAtPath);
            if (!isDirectory) //its a file
            {
                //Do with filepath
            }
            else{ //it's a folder, so recurse
                [self enumerateFolder:fullPath];
            }
        }
        return allHash;

    }
    -(void) enumerateFolder:(NSString*)fileName
    {
        NSDirectoryEnumerator *de= [[NSFileManager defaultManager] enumeratorAtPath:fileName];
        NSString* file;
        BOOL isDirectory;
        for(file in de)
        {
            //first check if it's a file
            BOOL fileExistsAtPath = [[NSFileManager defaultManager] fileExistsAtPath:file isDirectory:&isDirectory];
            if (fileExistsAtPath) {
                if (!isDirectory) //its a file
                { 
                  //Do with file  
                }
                else{ //it's a folder, so recurse
                    [self enumerateFolder:file];
                }
            }
            else printf("nenumeratefolder No file at path %s",[file UTF8String]);
        }
    }

在Swift中我们可以尝试以下操作:

let docsDir = NSHomeDirectory().appending("/Documents")
let localFileManager = FileManager()
let dirEnum = localFileManager.enumerator(atPath: docsDir)
while let file = dirEnum?.nextObject() as? String {
    if file.hasSuffix(".doc") {
        print(docsDir.appending("/(file)"))
    }
}
参考

https://developer.apple.com/documentation/foundation/filemanager/1408726-enumerator

相关内容

  • 没有找到相关文章

最新更新