78

I'm creating a folder to cache images inside Documents with my iPhone App. I want to be able to keep the size of this folder down to 1MB, so I need to to check the size in bytes of my folder.

I have code to calculate the size of file, but I need the size of the folder.

What would be the best way to do this?

joseph_carney
  • 1,535
  • 2
  • 14
  • 17
  • Using a NSDirectoryEnumerator and the fileAttributes method should do it. – zneak Feb 02 '10 at 23:30
  • Not sure what you mean, but I try to fully explore this in an answer [below](http://stackoverflow.com/a/12097436/45813). TL;DR version is that it looks like there's no escaping enumerating through the files. – Clay Bridges Aug 23 '12 at 17:56

15 Answers15

102

tl;dr

All the other answers are off :)

Problem

I'd like to add my two cents to this old question as there seem to be many answers that are all very similar but yield results that are in some cases very imprecise.

To understand why we first have to define what the size of a folder is. In my understanding (and probably the one of the OP) it is the amount of bytes that the directory including all of its contents uses on the volume. Or, put in another way:

It is the space becoming available if the directory would be completely removed.

I'm aware that this definition is not the only valid way to interpret the question but I do think it's what most use cases boil down to.

Error

The existing answers all take a very simple approach: Traverse the directory contents, adding up the sizes of (regular) files. This does not take a couple of subtleties into account.

  • The space used on the volume increments in blocks, not in bytes. Even a one byte file uses at least one block.
  • Files carry around meta data (like any number of extended attributes). This data must go somewhere.
  • HFS deploys file system compression to actually store the file using less bytes then its real length.

Solution

All of these reasons make the existing answers produce imprecise results. So I'm proposing this extension on NSFileManager (code on GitHub due to length: Swift 4, Objective C) to remedy the problem. It's also quite a bit faster, especially with directories containing a lot of files.

The core of the solution is to use NSURL's NSURLTotalFileAllocatedSizeKey or NSURLFileAllocatedSizeKey properties to retrieve file sizes.

Test

I've also set up a simple iOS test project, demonstrating the differences between the solutions. It shows how utterly wrong the results can be in some scenarios.

In the test I create a directory containing 100 small files (ranging from 0 to 800 bytes). The folderSize: method copied from some other answer calculates a total of 21 kB while my allocatedSize method yields 401 kB.

Proof

I made sure that the results of allocatedSize are closer to the correct value by calculating the difference of the available bytes on the volume before and after deleting the test directory. In my tests the difference was always exactly equal to the result of allocatedSize.

Please see Rob Napier's comment to understand that there's still room for improvement.

Performance

But there's another advantage: When calculating the size of a directory with 1000 files, on my iPhone 6 the folderSize: method takes about 250 ms while allocatedSize traverses the same hierarchy in 35 ms.

This is probably due to using NSFileManager's new(ish) enumeratorAtURL:includingPropertiesForKeys:options:errorHandler: API to traverse the hierarchy. This method let's you specify prefetched properties for the items to be iterated, resulting in less IO.

Results

Test `folderSize` (100 test files)
    size: 21 KB (21.368 bytes)
    time: 0.055 s
    actual bytes: 401 KB (401.408 bytes)

Test `allocatedSize` (100 test files)
    size: 401 KB (401.408 bytes)
    time: 0.048 s
    actual bytes: 401 KB (401.408 bytes)

Test `folderSize` (1000 test files)
    size: 2 MB (2.013.068 bytes)
    time: 0.263 s
    actual bytes: 4,1 MB (4.087.808 bytes)

Test `allocatedSize` (1000 test files)
    size: 4,1 MB (4.087.808 bytes)
    time: 0.034 s
    actual bytes: 4,1 MB (4.087.808 bytes)
Sam Spencer
  • 8,492
  • 12
  • 76
  • 133
Nikolai Ruhe
  • 81,520
  • 17
  • 180
  • 200
  • 2
    Very useful information. There is one (very) small wrinkle that likely distinguishes this from "the space becoming available if the directory would be completely removed." If there are any hard links from inodes outside the tree, then removing these hard links won't actually free the files. Hard links are not particularly common, less common across directories, and even less common on iOS, so this is a pretty minor amount and doesn't diminish from the usefulness of this technique. – Rob Napier Feb 23 '15 at 14:17
  • @RobNapier Thanks, I agree (I added this as a note in the actual source code). There are some other very subtle discrepancies, like meta data on subdirectories (can't be queried with the NSURL API) or space needed for symbolic links and other file system anomalies. But the results are at least an improvement over the simple file size solutions. – Nikolai Ruhe Feb 23 '15 at 14:25
  • 1
    Hi @NikolaiRuhe, I'm trying to use your class in a Swift project. I added it via a Objective-C header and I can can call the method like this `NSFileManager.defaultManager().nr_getAllocatedSize(UnsafeMutablePointer, ofDirectoryAtURL: NSURL!)`. However I'm not sure what should I pass in to the `size` parameter. I looked through your demo project but I'm still a little confused. – Isuru Feb 10 '16 at 08:55
  • 2
    @Isuru The size parameter is the actual result of the method and is returned by reference (which is a little awkward to use in Swift). If you don't want to simply port the method to a swiftier version, you can pass a variable by reference as follows: `var size = UInt64(0); nr_getAllocatedSize(&size​, ofDirectoryAtURL: someURL)` – Nikolai Ruhe Feb 10 '16 at 09:04
  • @NikolaiRuhe Oh I see. Thank you! – Isuru Feb 10 '16 at 09:06
  • @Isuru I just posted a [port to Swift](https://gist.github.com/NikolaiRuhe/eeb135d20c84a7097516). This might feel more natural to use. – Nikolai Ruhe Feb 10 '16 at 10:20
  • 1
    @NikolaiRuhe Wow that's more than I hoped for! Thanks so much. – Isuru Feb 10 '16 at 10:22
  • This doesn't work entirely in Swift3, there are issues when creating the enumerator. – Gary Kenyon Jul 13 '16 at 10:39
  • This is great! Is there any specific license for this code or a restriction on where it can be used? MIT? – Keiwan Sep 30 '17 at 10:36
  • 3
    @Keiwan I hereby release it under the MIT license. – Nikolai Ruhe Sep 30 '17 at 11:40
  • The only caveat I'd add to the Swift solution is the use of `UInt64` for bytes. I would recommend against this. Swift already treats bytes as integers and that is because when you need to compute sizes, you want to be able to work with negative numbers. If, for example, you need to compute how much over or under a directory's size is to a byte limit (i.e. var fat = dirSize - byteLimit), you will never get a negative number using unsigned integers and thus would never know how much smaller a directory is than its byte limit. Use `Int` or `Int64` if this matters to you. – trndjc Feb 03 '22 at 18:59
43

Cheers for that Alex, you helped a lot, have now written the following function which does the trick...

- (unsigned long long int)folderSize:(NSString *)folderPath {
    NSArray *filesArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:folderPath error:nil];
    NSEnumerator *filesEnumerator = [filesArray objectEnumerator];
    NSString *fileName;
    unsigned long long int fileSize = 0;

    while (fileName = [filesEnumerator nextObject]) {
        NSDictionary *fileDictionary = [[NSFileManager defaultManager] fileAttributesAtPath:[folderPath stringByAppendingPathComponent:fileName] traverseLink:YES];
        fileSize += [fileDictionary fileSize];
    }

    return fileSize;
}

It is coming up with the exact number of bytes as Finder does.

As an aside, Finder returns two numbers. One is the size on the disk and the other is the actual number of bytes.

For example, when I run this code on one of my folders, it comes back in the code with a 'fileSize' of 130398. When I check in Finder, it says the size is 201KB on disk (130,398 bytes).

Am a little unsure of what to go with here (201KB or 130,398 bytes) as the actual size. For now, I'll go on the safe side and cut my limit in half until I find out what this means exactly...

If anyone can add any more information to these differing numbers I'd appreciate it.

Cheers,

joseph_carney
  • 1,535
  • 2
  • 14
  • 17
  • There are two complications I can think of to explain the disparity: 1024 bytes is equivalent to 1 KB (or KiB? depends on who you ask) and also "block size", where a file's bytes can take up multiples of larger chunks of disk space — this is a file system level optimization that is dependent on the disk formatting and disk capacity. A 1024 byte file could actually take up a whole 16 KB block, for example, and thus be listed as a 16 KB file although it only uses 1024 bytes. – Alex Reynolds Feb 03 '10 at 02:57
  • @AlexReynolds - Correct. The "size on disk" means how much disk space is actually used to store the files. The second number is the size of the files themselves. Those are two different things, and the size on disk will almost always be larger. – DougW Oct 21 '11 at 23:33
  • 1
    @iphone_developer - One thing worth mentioning is that this method is **extremely** expensive. Calling it on a large folder with hundreds or thousands of small files will grind your app to a halt if done on the main thread. Nothing wrong with that if you need it, just worth pointing out. – DougW Oct 21 '11 at 23:36
  • is there any way to find size on disk programmatically? – tumbudu Mar 23 '15 at 09:42
  • The answer by Nikolai Ruhe is way way quicker for large quantities of files. – Kyle Apr 23 '18 at 13:03
37

This is how to get folder and file size in MB, KB and GB ---

1. Folder Size -

-(NSString *)sizeOfFolder:(NSString *)folderPath
{
    NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:folderPath error:nil];
    NSEnumerator *contentsEnumurator = [contents objectEnumerator];

    NSString *file;
    unsigned long long int folderSize = 0;

    while (file = [contentsEnumurator nextObject]) {
        NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[folderPath stringByAppendingPathComponent:file] error:nil];
        folderSize += [[fileAttributes objectForKey:NSFileSize] intValue];
    }

    //This line will give you formatted size from bytes ....
    NSString *folderSizeStr = [NSByteCountFormatter stringFromByteCount:folderSize countStyle:NSByteCountFormatterCountStyleFile];
    return folderSizeStr;
}

Note: In case of sub folders please use subpathsOfDirectoryAtPath: instead of contentsOfDirectoryAtPath:

2. File Size -

-(NSString *)sizeOfFile:(NSString *)filePath
{
    NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil];
    NSInteger fileSize = [[fileAttributes objectForKey:NSFileSize] integerValue];
    NSString *fileSizeStr = [NSByteCountFormatter stringFromByteCount:fileSize countStyle:NSByteCountFormatterCountStyleFile];
    return fileSizeStr;
}

---------- Swift 4.0 ----------

1. Folder Size -

func sizeOfFolder(_ folderPath: String) -> String? {
    do {
        let contents = try FileManager.default.contentsOfDirectory(atPath: folderPath)
        var folderSize: Int64 = 0
        for content in contents {
            do {
                let fullContentPath = folderPath + "/" + content
                let fileAttributes = try FileManager.default.attributesOfItem(atPath: fullContentPath)
                folderSize += fileAttributes[FileAttributeKey.size] as? Int64 ?? 0
            } catch _ {
                continue
            }
        }

        /// This line will give you formatted size from bytes ....
        let fileSizeStr = ByteCountFormatter.string(fromByteCount: folderSize, countStyle: ByteCountFormatter.CountStyle.file)
        return fileSizeStr

    } catch let error {
        print(error.localizedDescription)
        return nil
    }
}

2. File Size -

func sizeOfFile(_ filePath: String) -> String? {
    do {
        let fileAttributes = try FileManager.default.attributesOfItem(atPath: filePath)
        let folderSize = fileAttributes[FileAttributeKey.size] as? Int64 ?? 0
        let fileSizeStr = ByteCountFormatter.string(fromByteCount: folderSize, countStyle: ByteCountFormatter.CountStyle.file)
        return fileSizeStr
    } catch {
        print(error)
    }
    return nil
}
Suh Fangmbeng
  • 573
  • 4
  • 16
TheTiger
  • 13,264
  • 3
  • 57
  • 82
30

In iOS 5 the method -filesAttributesAtPath: is deprecated. Here is the version of the first code posted with the new method:

- (unsigned long long int)folderSize:(NSString *)folderPath {
    NSArray *filesArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:folderPath error:nil];
    NSEnumerator *filesEnumerator = [filesArray objectEnumerator];
    NSString *fileName;
    unsigned long long int fileSize = 0;

    while (fileName = [filesEnumerator nextObject]) {
        NSDictionary *fileDictionary = [[NSFileManager defaultManager] attributesOfItemAtPath:[folderPath stringByAppendingPathComponent:fileName] error:nil];
        fileSize += [fileDictionary fileSize];
    }

    return fileSize;
}
lukas
  • 2,300
  • 6
  • 28
  • 41
ndoc
  • 907
  • 8
  • 6
11

Something like the following should help get you started. You'll need to modify _documentsDirectory to your specific folder, though:

- (unsigned long long int) documentsFolderSize {
    NSFileManager *_manager = [NSFileManager defaultManager];
    NSArray *_documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *_documentsDirectory = [_documentPaths objectAtIndex:0];   
    NSArray *_documentsFileList;
    NSEnumerator *_documentsEnumerator;
    NSString *_documentFilePath;
    unsigned long long int _documentsFolderSize = 0;

    _documentsFileList = [_manager subpathsAtPath:_documentsDirectory];
    _documentsEnumerator = [_documentsFileList objectEnumerator];
    while (_documentFilePath = [_documentsEnumerator nextObject]) {
        NSDictionary *_documentFileAttributes = [_manager fileAttributesAtPath:[_documentsDirectory stringByAppendingPathComponent:_documentFilePath] traverseLink:YES];
        _documentsFolderSize += [_documentFileAttributes fileSize];
    }

    return _documentsFolderSize;
}
Alex Reynolds
  • 95,983
  • 54
  • 240
  • 345
4

Here's a swift 2.1/2.2 answer using extensions and building off of Rok's answer:

extension NSFileManager {
    func fileSizeAtPath(path: String) -> Int64 {
        do {
            let fileAttributes = try attributesOfItemAtPath(path)
            let fileSizeNumber = fileAttributes[NSFileSize]
            let fileSize = fileSizeNumber?.longLongValue
            return fileSize!
        } catch {
            print("error reading filesize, NSFileManager extension fileSizeAtPath")
            return 0
        }
    }

    func folderSizeAtPath(path: String) -> Int64 {
        var size : Int64 = 0
        do {
            let files = try subpathsOfDirectoryAtPath(path)
            for i in 0 ..< files.count {
                size += fileSizeAtPath((path as NSString).stringByAppendingPathComponent(files[i]) as String)
            }
        } catch {
            print("error reading directory, NSFileManager extension folderSizeAtPath")
        }
        return size
    }

    func format(size: Int64) -> String {
       let folderSizeStr = NSByteCountFormatter.stringFromByteCount(size, countStyle: NSByteCountFormatterCountStyle.File)
       return folderSizeStr
    }

}

Usage example:

let fileManager = NSFileManager.defaultManager()
let documentsDirPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
let dirSize: String = fileManager.format(fileManager.folderSizeAtPath(documentsDirPath))
Vitalii
  • 4,267
  • 1
  • 40
  • 45
Krtko
  • 1,055
  • 18
  • 24
4

I used this code to get the directory size of 2 directories, if one directory didnt exist, it would show Zero KB. Otherwise, the second half of the code will display the folder size along with the KB, MB, GB, respectively, and it will also display it in a clean format: 10.02 MB.

Try this something like this:

- (unsigned long long int)folderSize:(NSString *)folderPath {
    NSArray *filesArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:folderPath error:nil];
    NSEnumerator *filesEnumerator = [filesArray objectEnumerator];
    NSString *fileName;
    unsigned long long int fileSize = 0;

    while (fileName = [filesEnumerator nextObject]) {
        NSDictionary *fileDictionary = [[NSFileManager defaultManager] fileAttributesAtPath:[folderPath stringByAppendingPathComponent:fileName] traverseLink:YES];
        fileSize += [fileDictionary fileSize];
    } 

    return fileSize;
}

-(NSString *)getMPSize
{
    NSString*sizeTypeW = @"bytes";
    int app = [self folderSize:@"/PathToTheFolderYouWantTheSizeOf/"];
    NSFileManager *manager = [NSFileManager defaultManager];
    if([manager fileExistsAtPath:@"/AnotherFolder/"] == YES){

        int working = [self folderSize:@"/AnotherFolder/"];
        if(working<1){
            return @"Size: Zero KB";
        }else{
            if (working > 1024)
            {
                //Kilobytes
                working = working / 1024;

                sizeTypeW = @" KB";
            }

            if (working > 1024)
            {
                //Megabytes
                working = working / 1024;

                sizeTypeW = @" MB";
            }

            if (working > 1024)
            {
                //Gigabytes
                working = working / 1024;

                sizeTypeW = @" GB";
            }

            return [NSString stringWithFormat:@"App: %i MB, Working: %i %@ ",app/1024/1024, working,sizeTypeW];
        }

    }else{
        return [NSString stringWithFormat:@"App: %i MB, Working: Zero KB",app/1024/1024];
    }
    [manager release];
}
WrightsCS
  • 50,551
  • 22
  • 134
  • 186
3

Updated Method using enumeration block

Calculate Folder Size with only files

- (NSString *)sizeOfFolder:(NSString *)folderPath {
    NSArray *folderContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:folderPath error:nil];
    __block unsigned long long int folderSize = 0;

    [folderContents enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[folderPath stringByAppendingPathComponent:obj] error:nil];
        folderSize += [[fileAttributes objectForKey:NSFileSize] intValue];
    }];
    NSString *folderSizeStr = [NSByteCountFormatter stringFromByteCount:folderSize countStyle:NSByteCountFormatterCountStyleFile];
    return folderSizeStr;
}

Calculate Folder Size with other sub directories in the folder

 NSArray *folderContents = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:folderPath error:nil];

Get File Size

- (NSString *)sizeOfFile:(NSString *)filePath {
    NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil];
    NSInteger fileSize = [[fileAttributes objectForKey:NSFileSize] integerValue];
    NSString *fileSizeString = [NSByteCountFormatter stringFromByteCount:fileSize countStyle:NSByteCountFormatterCountStyleFile];
    return fileSizeString;
}
icodebuster
  • 8,890
  • 7
  • 62
  • 65
3

Here is the Swift 3 equivalent of a FileManager extension based off of @vitalii extension:

extension FileManager {

func fileSizeAtPath(path: String) -> Int64 {
    do {
        let fileAttributes = try attributesOfItem(atPath: path)
        let fileSizeNumber = fileAttributes[FileAttributeKey.size] as? NSNumber
        let fileSize = fileSizeNumber?.int64Value
        return fileSize!
    } catch {
        print("error reading filesize, NSFileManager extension fileSizeAtPath")
        return 0
    }
}

func folderSizeAtPath(path: String) -> Int64 {
    var size : Int64 = 0
    do {
        let files = try subpathsOfDirectory(atPath: path)
        for i in 0 ..< files.count {
            size += fileSizeAtPath(path:path.appending("/"+files[i]))
        }
    } catch {
        print("error reading directory, NSFileManager extension folderSizeAtPath")
    }
    return size
}

func format(size: Int64) -> String {
    let folderSizeStr = ByteCountFormatter.string(fromByteCount: size, countStyle: ByteCountFormatter.CountStyle.file)
    return folderSizeStr
}}
Larry Mickie
  • 441
  • 4
  • 9
2

I think use Unix C method is better for performance.

+ (long long) folderSizeAtPath: (const char*)folderPath {
  long long folderSize = 0;
  DIR* dir = opendir(folderPath);
  if (dir == NULL) return 0;
  struct dirent* child;
  while ((child = readdir(dir))!=NULL) {
    if (child->d_type == DT_DIR
        && child->d_name[0] == '.'
        && (child->d_name[1] == 0 // ignore .
            ||
            (child->d_name[1] == '.' && child->d_name[2] == 0) // ignore dir ..
           ))
      continue;

    int folderPathLength = strlen(folderPath);
    char childPath[1024]; // child 
    stpcpy(childPath, folderPath);
    if (folderPath[folderPathLength-1] != '/'){
      childPath[folderPathLength] = '/';
      folderPathLength++;
    }
    stpcpy(childPath+folderPathLength, child->d_name);
    childPath[folderPathLength + child->d_namlen] = 0;
    if (child->d_type == DT_DIR){ // directory
      folderSize += [self _folderSizeAtPath:childPath]; // 
      // add folder size
      struct stat st;
      if (lstat(childPath, &st) == 0)
        folderSize += st.st_size;
    } else if (child->d_type == DT_REG || child->d_type == DT_LNK){ // file or link
      struct stat st;
      if (lstat(childPath, &st) == 0)
        folderSize += st.st_size;
    }
  }
  return folderSize;
}
john.k.doe
  • 7,533
  • 2
  • 37
  • 64
ZYiOS
  • 5,204
  • 3
  • 39
  • 45
1

I cleaned up a bit the first answer's implementation before using it, so it no longer throws deprecated warnings + using fast enumeration.

/**
 *  Calculates the size of a folder.
 *
 *  @param  folderPath  The path of the folder
 *
 *  @return folder size in bytes
 */
- (unsigned long long int)folderSize:(NSString *)folderPath {
    NSFileManager *fm = [NSFileManager defaultManager];
    NSArray *filesArray = [fm subpathsOfDirectoryAtPath:folderPath error:nil];
    unsigned long long int fileSize = 0;

    NSError *error;
    for(NSString *fileName in filesArray) {
        error = nil;
        NSDictionary *fileDictionary = [fm attributesOfItemAtPath:[folderPath     stringByAppendingPathComponent:fileName] error:&error];
        if (!error) {
            fileSize += [fileDictionary fileSize];
        }else{
            NSLog(@"ERROR: %@", error);
        }
    }

    return fileSize;
}
Stoto
  • 410
  • 4
  • 10
1

Swift Implementation

class func folderSize(folderPath:String) -> UInt{

    // @see http://stackoverflow.com/questions/2188469/calculate-the-size-of-a-folder

    let filesArray:[String] = NSFileManager.defaultManager().subpathsOfDirectoryAtPath(folderPath, error: nil)! as [String]
    var fileSize:UInt = 0

    for fileName in filesArray{
        let filePath = folderPath.stringByAppendingPathComponent(fileName)
        let fileDictionary:NSDictionary = NSFileManager.defaultManager().attributesOfItemAtPath(filePath, error: nil)!
        fileSize += UInt(fileDictionary.fileSize())

    }

    return fileSize
}
Luyu Zhang
  • 19
  • 2
1

if we want to get the size of any file then here is a method, where we only need to pass path of that file.

- (unsigned long long int) fileSizeAt:(NSString *)path {
    NSFileManager *_manager = [NSFileManager defaultManager];
    return [[_manager fileAttributesAtPath:path traverseLink:YES] fileSize];
}
Prakash Raj
  • 1,943
  • 1
  • 15
  • 13
  • with your suggestion, you will only handle the directory placeholder size. if you'd like to calculate the directory size with all of the contents, you must get the each file size inside the directory with some loop operation and add one by one. like above examples. and also, fileAttributesAtPath method deprecated long long time ago. – ytur Mar 24 '13 at 13:00
  • fileAttributesAtPath is deprecated – user1105951 Nov 17 '16 at 07:55
0

Not sure if this helps anyone, but I wanted to relate some of my findings (some inspired by @zneak's comment above).

  1. I could not find any shortcuts using NSDirectoryEnumerator to avoid enumerating through files to get the total contained size of a directory.

  2. For my tests, using -[NSFileManager subpathsOfDirectoryAtPath:path error:nil] was faster than using -[NSFileManager enumeratorAtPath:path]. This looks to me like it might be a classic time/space tradeoff, as subPaths... creates an NSArray on which it then iterates, where enumerator... might not.

Some background on #1. Assuming:

NSFileManager *fileMan = [NSFileManager defaultManager];
NSString *dirPath = @"/"; // references some directory

Then

[fileMan enumeratorAtPath:dirPath] fileAttributes]

returns nil. The correct attribute accessor is directoryAttributes, but

[fileMan enumeratorAtPath:dirPath] directoryAttributes] fileSize]

returns the size of the directory information, not the recursive sum of the sizes of all contained files (a lá ⌘-I in Finder).

Clay Bridges
  • 11,602
  • 10
  • 68
  • 118
0

I've created a simple NSFileManager extension:

extension NSFileManager {
  func fileSizeAtPath(path: String) -> Int {
    return attributesOfItemAtPath(path, error: nil)?[NSFileSize] as? Int ?? 0
  }

  func folderSizeAtPath(path: String) -> Int {
    var size = 0
    for file in subpathsOfDirectoryAtPath(path, error: nil) as? [String] ?? [] {
      size += fileSizeAtPath(path.stringByAppendingPathComponent(file))
    }
    return size
  }
}

You can get the file size:

NSFileManager.defaultManager().fileSizeAtPath("file path")

and the folder size:

NSFileManager.defaultManager().folderSizeAtPath("folder path")
Rok Gregorič
  • 2,377
  • 1
  • 13
  • 11