Check the attribute of items in a directory in Obj

2019-06-14 09:56发布

问题:

I have made this little code to check how many subdirectories are in a given directory. It checks only the first level, is there anyway I can make it simplier? I have added comments, maybe easier to understand my intention. Thank you!

    #import < Foundation/Foundation.h >            
            int main (int argc, const char * argv[]){
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];



// insert code here...
NSFileManager *filemgr;
NSMutableArray *listOfFiles;
NSDictionary *listOfFolders;
NSDictionary *controllDir;
int i, count;
NSString *myPath;

filemgr = [NSFileManager defaultManager];

myPath = @"/";

// list the files in the given directory (myPath)

listOfFiles = [filemgr directoryContentsAtPath: myPath];

// count the number of elements in the array
count = [listOfFiles count];

// check them one by one
for (i = 0; i < count; i++)
{
    // I need the full path
   NSString *filePath =[NSString stringWithFormat:@"%@/%@", myPath, [listOfFiles objectAtIndex: i]];

    // add every item with its attributes
    listOfFolders = [filemgr attributesOfItemAtPath:filePath error:NULL];

    // to avoid typo get the attribute and create a string
    controllDir = [filemgr attributesOfItemAtPath:@"/" error:NULL];
    NSString *toCheck = [NSString stringWithFormat:@"%@", [controllDir objectForKey:NSFileType]];   

    // the folder elements one by one
    NSString *fileType = [NSString stringWithFormat:@"%@", [listOfFolders objectForKey:NSFileType]];    


    if([toCheck isEqualToString:fileType])
        {
            NSLog(@"NAME: %@  TYPE: %@" ,[listOfFiles objectAtIndex:i],[listOfFolders objectForKey:NSFileType]);
        }                
}            

[pool drain];
return 0;
}

回答1:

    NSURL *url = [NSURL fileURLWithPath:@"/Users"];
    NSError *error;
    NSArray *items = [[NSFileManager defaultManager]
                      contentsOfDirectoryAtURL:url
                      includingPropertiesForKeys:[NSArray array]
                      options:0
                      error:&error];

    NSMutableArray *dirs = [NSMutableArray array];
    for (NSURL *url in items) {
        if (CFURLHasDirectoryPath((CFURLRef)url)) {
            [dirs addObject:url];
        }
    }
}

You can get fancy with blocks this way:

NSPredicate *predicate = [NSPredicate predicateWithBlock:
        ^BOOL (id evaluatedObject, NSDictionary *bindings){
            return CFURLHasDirectoryPath((CFURLRef)evaluatedObject); }];
NSArray *dirs = [items filteredArrayUsingPredicate:predicate]);

Of note here is that it only hits the disk the one time, and it doesn't spend any time fetching unneeded attributes. Once you construct the NSURL, you can always tell if it's a directory because it ends in a / (this is specified behavior). That's all CFURLHasDirectoryPath() is doing. It doesn't actually hit the disk.



回答2:

Brief thoughts (posting from a cell phone):

  • use an NSDirectoryEnumerator.
  • it has a method called fileAttributes that will return an NSDictionary with the item's attributes.
  • NSDictionary has a fileType method that will return a constant to indicate the kind of the item.
  • there's a nice constant called NSFileTypeDirectory you can use for comparison.


回答3:

How's this?

NSFileManager *fm = [NSFileManager defaultManager];
NSError *error;
NSArray *subpaths = [fm contentsOfDirectoryAtPath:myPath error:&error];
if (!subpaths) ...handle error.
NSMutableArray *subdirs = [NSMutableArray array];
for (NSString *name in subpaths)
{
    NSString *subpath = [myPath stringByAppendingPathComponent:name];
    BOOL isDir;
    if ([fm fileExistsAtPath:subpath isDirectory:&isDir] &&
        isDir)
    {
        [subdirs addObject:subpath];
    }
}

Now the subdirs array contains all of the immediate subdirectories.