web-dev-qa-db-ja.com

ネストされたフォルダーを持つフォルダー内のファイルの繰り返し-Cocoa

ネストされたフォルダー内に存在するファイルを含む、フォルダー内のすべてのファイルにアクセスする必要があります。フォルダーの例は次のようになります。

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

フォルダーではない「動物」内のすべてのファイルでプロセスを実行したいとします。フォルダ「動物」とそのすべてのサブフォルダを反復処理して、すべてのファイルにアクセスする最良の方法は何でしょうか?

ありがとう。

40
minimalpop

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
    }
}
94
user557219

たぶん、あなたはこのようなものを使うことができます:

+(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];
    }
  }
}
25
Karl von Moor

Swiftバージョン:

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.hasPrefix(".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)
    }
}
14
Esqarrouth

このコードは私のために働いた。

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

-subpathsOfDirectoryAtPath:rootPath 、ファイルURLおよび最新のObjective-C nullabilityの添え字付き。

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))
    }
}
0
mz2