JackVaughn JackVaughn - 7 days ago 8
Swift Question

How To Get Directory Size With Swift On OS X

I am trying to get the size of a directory, as well as it's content on OS X using Swift. So far, I have only been able to get the size of the directory itself, with none of it's content. For most of my directories it generally shows a value of 6,148 bytes but it does varie.

I have tried the directorySize() function from the file below but it returned 6,148 bytes as well.

https://github.com/amosavian/ExtDownloader/blob/2f7dba2ec1edd07282725ff47080e5e7af7dabea/Utility.swift

I tried the top 2 answers from this question, but was unsure what argument it needed passed Swift to the Objective-C function. I believe it wants a pointer (I am a beginning programmer in learning).

Calculate the size of a folder

And I could not get the Swift answer from here to work for my purpose either.

How to get the file size given a path?

I am using Xcode 7.0 and running OS X 10.10.5.

Answer
// get your directory url
let documentsDirectoryURL =  try! NSFileManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true)
// check if the url is a directory
var bool: ObjCBool = false
if NSFileManager().fileExistsAtPath(documentsDirectoryURL.path!, isDirectory: &bool) {
    if bool.boolValue {
        print("url is a folder url")
        // lets get the folder files
        let fileManager =  NSFileManager.defaultManager()
        let files = try! fileManager.contentsOfDirectoryAtURL(documentsDirectoryURL, includingPropertiesForKeys: nil, options: [])
        var folderFileSizeInBytes = 0
        for file in files {
            folderFileSizeInBytes +=  try! (fileManager.attributesOfItemAtPath(file.path!) as NSDictionary).fileSize().hashValue
        }
        // format it using NSByteCountFormatter to display it properly
        let  byteCountFormatter =  NSByteCountFormatter()
        byteCountFormatter.allowedUnits = .UseBytes
        byteCountFormatter.countStyle = .File
        let folderSizeToDisplay = byteCountFormatter.stringFromByteCount(Int64(folderFileSizeInBytes))
        print(folderSizeToDisplay)  // "X,XXX,XXX bytes"
    }
}

If you would like to include all subFolders, hidden files and package descendants you need to use enumeratorAtURL as follow:

let documentsDirectoryURL =  try! NSFileManager().URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true)
var bool: ObjCBool = false
if NSFileManager().fileExistsAtPath(documentsDirectoryURL.path!, isDirectory: &bool) {
    if bool.boolValue {
        let fileManager =  NSFileManager.defaultManager()
        var folderFileSizeInBytes = 0
        if let filesEnumerator = fileManager.enumeratorAtURL(documentsDirectoryURL, includingPropertiesForKeys: nil, options: [], errorHandler: {
            (url, error) -> Bool in
                print(url.path!)
                print(error.localizedDescription)
                return true
        }) {
            while let fileURL = filesEnumerator.nextObject() as? NSURL {
                do {
                    let attributes = try fileManager.attributesOfItemAtPath(fileURL.path!) as NSDictionary
                    folderFileSizeInBytes += attributes.fileSize().hashValue
                } catch let error as NSError {
                    print(error.localizedDescription)
                }
            }
        }
        let  byteCountFormatter =  NSByteCountFormatter()
        byteCountFormatter.allowedUnits = .UseBytes
        byteCountFormatter.countStyle = .File
        let folderSizeToDisplay = byteCountFormatter.stringFromByteCount(Int64(folderFileSizeInBytes))
        print(folderSizeToDisplay)  // "X,XXX,XXX bytes"
    }
}