使用嵌套文件夹迭代文件夹中的文件 - Cocoa

时间:2011-04-21 20:33:23

标签: macos cocoa directory iteration

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

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

假设我想对不是文件夹的“动物”中的每个文件运行一个进程。迭代文件夹“animals”及其所有子文件夹访问每个文件的最佳方法是什么?

感谢。

6 个答案:

答案 0 :(得分:94)

使用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:^(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
    }
}

答案 1 :(得分:25)

也许你可以使用这样的东西:

+(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];
    }
  }
}

答案 2 :(得分:14)

这是一个快速版本:

#spoonbill-outer {
position: fixed;
right: 0px;
bottom: 0px;
margin: 22px;
z-index: 10;
}

答案 3 :(得分:1)

这段代码对我有用。

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

答案 4 :(得分:0)

这是一个使用-subpathsOfDirectoryAtPath:rootPath的解决方案,包含文件网址和现代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))
    }
}

答案 5 :(得分:0)

在Swift中,我们可以尝试以下方法。

function maxMin(arr){ 
let temp = [];
let small = 0;
let large = arr.length - 1;

for (let i = 0; i < arr.length; i++) {
  if (small < large) {
  temp.push(arr[large]);
  temp.push(arr[small]);
  small++;
  large--; 
   }

}
//length of array if its  not even
if(arr.length % 2 !==0){
  let i = Math.floor(arr.length/2)
  temp.push(arr[i])
}
 return temp;
}

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