Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 575
theCalmChameleon Avatar asked Sep 28 '15 01:09

theCalmChameleon


People also ask

How do I check the size of a file in Swift?

You can call . fileSize() on attr to get file size.

How do I get the size of a directory in C?

The basic approach is as follows: Use the file system APIs to enumerate the entries in the directory. For each entry: If that entry is a file, use the appropriate file system API to get its size and add it to the total.


1 Answers

update: Xcode 11.4.1 • Swift 5.2


extension URL {
    /// check if the URL is a directory and if it is reachable 
    func isDirectoryAndReachable() throws -> Bool {
        guard try resourceValues(forKeys: [.isDirectoryKey]).isDirectory == true else {
            return false
        }
        return try checkResourceIsReachable()
    }

    /// returns total allocated size of a the directory including its subFolders or not
    func directoryTotalAllocatedSize(includingSubfolders: Bool = false) throws -> Int? {
        guard try isDirectoryAndReachable() else { return nil }
        if includingSubfolders {
            guard
                let urls = FileManager.default.enumerator(at: self, includingPropertiesForKeys: nil)?.allObjects as? [URL] else { return nil }
            return try urls.lazy.reduce(0) {
                    (try $1.resourceValues(forKeys: [.totalFileAllocatedSizeKey]).totalFileAllocatedSize ?? 0) + $0
            }
        }
        return try FileManager.default.contentsOfDirectory(at: self, includingPropertiesForKeys: nil).lazy.reduce(0) {
                 (try $1.resourceValues(forKeys: [.totalFileAllocatedSizeKey])
                    .totalFileAllocatedSize ?? 0) + $0
        }
    }

    /// returns the directory total size on disk
    func sizeOnDisk() throws -> String? {
        guard let size = try directoryTotalAllocatedSize(includingSubfolders: true) else { return nil }
        URL.byteCountFormatter.countStyle = .file
        guard let byteCount = URL.byteCountFormatter.string(for: size) else { return nil}
        return byteCount + " on disk"
    }
    private static let byteCountFormatter = ByteCountFormatter()
}

usage:

do {
    let documentDirectory = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
    if let sizeOnDisk = try documentDirectory.sizeOnDisk() {
        print("Size:", sizeOnDisk) // Size: 3.15 GB on disk
    }
} catch {
    print(error)
}
like image 86
Leo Dabus Avatar answered Nov 03 '22 09:11

Leo Dabus