Skip to content

Instantly share code, notes, and snippets.

@kristopherjohnson
Last active November 29, 2023 12:32
Show Gist options
  • Select an option

  • Save kristopherjohnson/4bafee0b489add42a61f to your computer and use it in GitHub Desktop.

Select an option

Save kristopherjohnson/4bafee0b489add42a61f to your computer and use it in GitHub Desktop.
Example of using opendir/readdir/closedir with Swift
import Foundation
// Get current working directory
var wdbuf: [Int8] = Array(count: Int(MAXNAMLEN), repeatedValue: 0)
let workingDirectory = getcwd(&wdbuf, UInt(MAXNAMLEN))
// Open the directory
let dir = opendir(workingDirectory)
if dir != nil {
// Use readdir to get each element
var dirent = readdir(dir)
while dirent != nil {
var name: [CChar] = Array()
// dirent.d_name is defined as a tuple with
// MAXNAMLEN elements. The only way to
// iterate over those elements is via
// reflection
//
// Credit: dankogi at http://stackoverflow.com/questions/24299045/any-way-to-iterate-a-tuple-in-swift
let d_namlen = dirent.memory.d_namlen
let d_name = dirent.memory.d_name
let mirror = reflect(d_name)
for i in 0..<d_namlen {
let (s, m) = mirror[Int(i)]
name.append(m.value as Int8)
}
// null-terminate it and convert to a string
name.append(0)
if let s = String.fromCString(name) {
println(s)
}
dirent = readdir(dir)
}
closedir(dir)
}
@josipbernat
Copy link

This is a similar version of this code adopted to Swift 5.9. It excludes ".", ".." and similar files because I find them useless. Also it returns [URL] instead of [String].

extension FileManager {
    
    func contentsOfDirectoryUsingCAPI(url: URL) -> [URL]? {
        guard let folderPathCString = url.path.cString(using: .utf8) else {
            return nil
        }

        // Open the directory
        guard let dir = opendir(folderPathCString) else {
            return nil
        }

        var contentsOfDirectory = [URL]()

        // Use readdir to get each element
        while let entry = readdir(dir) {
            let d_namlen = Int(entry.pointee.d_namlen)
            let d_name = withUnsafePointer(to: &entry.pointee.d_name) {
                $0.withMemoryRebound(to: CChar.self, capacity: d_namlen) { ptr in
                    String(cString: ptr)
                }
            }

            if !d_name.allSatisfy({ $0 == "." }) {
                let fileURL = url.appendingPathComponent(d_name)
                contentsOfDirectory.append(fileURL)
            }
        }

        closedir(dir)

        return contentsOfDirectory
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment