Как получить общее/доступное/использованное пространство USB-накопителя в MacOS - Swift?

Как определить общее, доступное и используемое пространство USB-накопителя в Swift (MacOS)?

Об этом есть несколько хороших сообщений (пример: Как получить общее дисковое пространство и свободное дисковое пространство с помощью AttributesOfFileSystemForpaths в swift 2.0 и https://developer.apple.com/documentation/foundation/urlresourcekey/checking_volume_storage_capacity), но все они просто занимают место на диске операционной системы, а не на USB-накопителе.

Например, у меня есть USB-накопитель емкостью 64 ГБ с именем тома myusb, поэтому MacOS монтирует диск в /Volumes/myusb. Finder показывает общее пространство USB-накопителя как 62,91 ГБ, доступное как 62,29 ГБ и используемое как 625 999 872 байта.

Проблема, похоже, в том, что когда я указываю путь к USB-накопителю, поскольку он, очевидно, является частью основного / пути, он возвращает информацию для /, который является моим диском ОС, а не USB-накопитель.

Вот что я делаю, когда пытаюсь определить свободное место на USB-накопителе и возвращает значение 292298430687 байт (это доступное пространство на диске моей ОС, а не на USB-накопителе):

/**
   Returns URL of root of USB drive - i.e. /Volumes/myusb
   Uses bundleURL as .app file being executed is located on the USB drive
*/
static func getRootURL() -> URL {
    let bundlePath = Bundle.main.bundleURL
    let bundlePathComponents = bundlePath.pathComponents
        
    let destinationRootPathURL = URL(fileURLWithPath: bundlePathComponents[0])
        .appendingPathComponent(bundlePathComponents[1])
        .appendingPathComponent(bundlePathComponents[2])
        
    return destinationRootPathURL
}

/**
   returns free space of USB drive
*/
func getAvailableSpaceInBytes() -> Int64 {
    if #available(OSX 10.13, *) {
        if let freeSpace = try? getRootURL().resourceValues(forKeys: [URLResourceKey.volumeAvailableCapacityForImportantUsageKey])
                .volumeAvailableCapacityForImportantUsage {
                return freeSpace
        }
    } else {
        // Fallback on earlier versions
        guard let systemAttributes = try? FileManager.default.attributesOfFileSystem(forPath: getRootURL().path),
              let freeSize = systemAttributes[FileAttributeKey.systemFreeSize] as? NSNumber
        else {
            // something failed so return nil
            return 0
        }
            
        return freeSize.int64Value
    }
        
        return 0
    }

person Monty    schedule 24.03.2021    source источник


Ответы (1)


Вы можете использовать метод FileManager mountedVolumeURLs, чтобы получить все смонтированные тома и получить от него ключ/значение ресурса volumeAvailableCapacityForImportantUsage:


extension FileManager {
    static var mountedVolumes: [URL] {
        (FileManager.default.mountedVolumeURLs(includingResourceValuesForKeys: nil) ?? []).filter({$0.path.hasPrefix("/Volumes/")})
    }
}

extension URL {
    var volumeTotalCapacity: Int? {
        (try? resourceValues(forKeys: [.volumeTotalCapacityKey]))?.volumeTotalCapacity
    }
    var volumeAvailableCapacityForImportantUsage: Int64? {
        (try? resourceValues(forKeys: [.volumeAvailableCapacityForImportantUsageKey]))?.volumeAvailableCapacityForImportantUsage
    }
    var name: String? {
        (try? resourceValues(forKeys: [.nameKey]))?.name
    }
    
}

Использование:

for url in FileManager.mountedVolumes {
    print(url.name ?? "Untitled")
    print("Capacity:", url.volumeTotalCapacity ?? "nil")
    print("Available:", url.volumeAvailableCapacityForImportantUsage ?? "nil")
    print("Used:", (try? url.sizeOnDisk()) ?? "nil") // check the other link below
}

Для USB-накопителя емкостью 16 ГБ с установщиком BigSur приведенный выше код будет напечатан

Установите macOS Big Sur
Емкость: 15180193792
Доступно: 2232998976
Используется: 12,93 ГБ на диске


Чтобы получить используемое пространство тома sizeOnDisk, вы можете проверить этот сообщение

person Leo Dabus    schedule 24.03.2021
comment
Это сработало отлично. Спасибо за подробный и понятный ответ - person Monty; 24.03.2021