objective c - Iterar a través de archivos en una carpeta con carpetas anidadas-Cocoa
objective-c macos (5)
Necesito acceder a todos los archivos en una carpeta, incluido el archivo que existe dentro de las carpetas anidadas. Una carpeta de ejemplo podría verse así.
animals/
-k.txt
-d.jpg
cat/
-r.txt
-z.jpg
tiger/
-a.jpg
-p.pdf
dog/
-n.txt
-f.jpg
-p.pdf
Digamos que quería ejecutar un proceso en cada archivo dentro de "animales" que no es una carpeta. ¿Cuál sería la mejor manera de recorrer la carpeta "animals" y todas sus subcarpetas para acceder a cada archivo?
Gracias.
Aquí hay una solución que usa -subpathsOfDirectoryAtPath:rootPath
, con URLs de archivos y modernas campanas y silbidos de nulabilidad de 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
... y lo mismo en 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))
}
}
Aquí hay una versión rápida:
func openEachFileAt(path: String) {
var file: String
var subs = NSFileManager.defaultManager().subpathsOfDirectoryAtPath(path, error: nil) as! [String]
var totalFiles = subs.count
println(totalFiles)
for sub in subs {
if sub.rangeOfString(".DS_Store") != nil {
//a DS_Store file
} else if sub.rangeOfString(".xcassets") != nil {
//a xcassets file
} else if (sub as NSString).substringWithRange(NSRange(location: 0, length: 4)) == ".git" {
//a git file
} else if sub.pathExtension == "swift" {
//a swift file
} else if sub.pathExtension == "m" {
//a objc file
} else if sub.pathExtension == "h" {
//a header file
} else {
}
var fullPath = path.stringByAppendingPathComponent(sub)
}
}
Este código funcionó para mí.
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]);
}
}
Tal vez puedas usar algo como esto:
+(void)openEachFileAt:(NSString*)path
{
NSString* file;
NSDirectoryEnumerator* enumerator = [[NSFileManager defaultManager] enumeratorAtPath:path];
while (file = [enumerator nextObject])
{
// 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];
}
}
}
Use NSDirectoryEnumerator
para enumerar recursivamente los archivos y directorios en el directorio que desee, y pídale que le diga si se trata de un archivo o directorio. Lo siguiente se basa en el ejemplo enumerado en la documentación para -[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
}
}