macOS Swift Dateioperationsbeispiele

macOS Swift Dateioperationsbeispiele einschließlich Textdatei-Lesen/Schreiben, Datei-Kopieren/Verschieben, Verzeichnisdurchlauf und Dateivalidierung

💻 Textdatei-Lesen/Schreiben swift

🟢 simple ⭐⭐

Textdateien mit verschiedenen Kodierungsoptionen und Fehlerbehandlung lesen und schreiben

⏱️ 20 min 🏷️ swift, macos, file operations, io
Prerequisites: Basic Swift knowledge, Foundation framework
// macOS Swift Text File Read/Write Examples
// Using Foundation framework

import Foundation

// 1. Basic Text File Writing
class TextFileWriter {

    // Write simple text to file
    static func writeText(to path: String, text: String) throws {
        try text.write(toFile: path, atomically: true, encoding: .utf8)
        print("Text written to: \(path)")
    }

    // Write text with specific encoding
    static func writeText(to path: String, text: String, encoding: String.Encoding) throws {
        try text.write(toFile: path, atomically: true, encoding: encoding)
        print("Text written with \(encoding) to: \(path)")
    }

    // Append text to existing file
    static func appendText(to path: String, text: String) throws {
        let fileHandle = FileHandle(forWritingAtPath: path)
        if let handle = fileHandle {
            handle.seekToEndOfFile()
            if let data = text.data(using: .utf8) {
                handle.write(data)
            }
            handle.closeFile()
            print("Text appended to: \(path)")
        } else {
            // File doesn't exist, create new
            try writeText(to: path, text: text)
        }
    }

    // Write text with line endings
    static func writeLines(to path: String, lines: [String]) throws {
        let content = lines.joined(separator: "\n")
        try writeText(to: path, text: content)
        print("\(lines.count) lines written to: \(path)")
    }

    // Write with FileHandle (more control)
    static func writeWithFileHandle(to path: String, text: String) throws {
        guard let data = text.data(using: .utf8) else {
            throw NSError(domain: "TextError", code: 1, userInfo: [
                NSLocalizedDescriptionKey: "Failed to convert text to data"
            ])
        }

        FileManager.default.createFile(atPath: path, contents: data, attributes: nil)
        print("File created at: \(path)")
    }
}

// 2. Basic Text File Reading
class TextFileReader {

    // Read entire file as string
    static func readText(from path: String) throws -> String {
        let content = try String(contentsOfFile: path, encoding: .utf8)
        print("Read \(content.count) characters from: \(path)")
        return content
    }

    // Read with encoding detection
    static func readTextWithEncoding(from path: String) throws -> String {
        let encodings: [String.Encoding] = [.utf8, .utf16, .ascii, .isoLatin1]

        for encoding in encodings {
            if let content = try? String(contentsOfFile: path, encoding: encoding) {
                print("Read file with encoding: \(encoding)")
                return content
            }
        }

        throw NSError(domain: "ReadError", code: 1, userInfo: [
            NSLocalizedDescriptionKey: "Could not read file with any supported encoding"
        ])
    }

    // Read line by line
    static func readLines(from path: String) throws -> [String] {
        let content = try readText(from: path)
        let lines = content.components(separatedBy: .newlines)
        print("Read \(lines.count) lines from: \(path)")
        return lines
    }

    // Read with FileHandle (for large files)
    static func readWithFileHandle(from path: String) throws -> String {
        guard let fileHandle = FileHandle(forReadingAtPath: path) else {
            throw NSError(domain: "ReadError", code: 1, userInfo: [
                NSLocalizedDescriptionKey: "Failed to open file for reading"
            ])
        }

        defer { fileHandle.closeFile() }

        let data = fileHandle.readDataToEndOfFile()
        guard let content = String(data: data, encoding: .utf8) else {
            throw NSError(domain: "ReadError", code: 2, userInfo: [
                NSLocalizedDescriptionKey: "Failed to decode file data"
            ])
        }

        print("Read \(data.count) bytes using FileHandle")
        return content
    }

    // Read specific range
    static func readRange(from path: String, start: Int, length: Int) throws -> String {
        guard let fileHandle = FileHandle(forReadingAtPath: path) else {
            throw NSError(domain: "ReadError", code: 1, userInfo: [
                NSLocalizedDescriptionKey: "Failed to open file for reading"
            ])
        }

        defer { fileHandle.closeFile() }

        fileHandle.seek(toFileOffset: UInt64(start))
        let data = fileHandle.readData(ofLength: length)

        guard let content = String(data: data, encoding: .utf8) else {
            throw NSError(domain: "ReadError", code: 2, userInfo: [
                NSLocalizedDescriptionKey: "Failed to decode file data"
            ])
        }

        print("Read \(length) bytes from offset \(start)")
        return content
    }
}

// 3. File Info Helper
class FileInfoHelper {

    static func getFileAttributes(at path: String) -> [FileAttributeKey: Any]? {
        guard let attributes = try? FileManager.default.attributesOfItem(atPath: path) else {
            return nil
        }
        return attributes
    }

    static func printFileInfo(at path: String) {
        guard let attributes = getFileAttributes(at: path) else {
            print("No file info available for: \(path)")
            return
        }

        print("\n--- File Info: \(path) ---")
        if let size = attributes[.size] as? UInt64 {
            print("Size: \(size) bytes")
        }
        if let modified = attributes[.modificationDate] as? Date {
            print("Modified: \(modified)")
        }
        if let type = attributes[.type] as? FileAttributeType {
            print("Type: \(type.rawValue)")
        }
    }
}

// 4. Advanced Text Operations
class AdvancedTextOperations {

    // Read file with line processing callback
    static func processLinesInFile(at path: String, processor: (String, Int) -> Void) throws {
        let lines = try TextFileReader.readLines(from: path)
        for (index, line) in lines.enumerated() {
            processor(line, index)
        }
    }

    // Search for text in file
    static func searchInFile(at path: String, searchText: String) -> [(line: String, lineNumber: Int)] {
        guard let lines = try? TextFileReader.readLines(from: path) else {
            return []
        }

        var results: [(String, Int)] = []

        for (index, line) in lines.enumerated() {
            if line.range(of: searchText, options: .caseInsensitive) != nil {
                results.append((line, index + 1))
            }
        }

        return results
    }

    // Replace text in file
    static func replaceInFile(at path: String, searchText: String, replaceWith: String) throws {
        var content = try TextFileReader.readText(from: path)
        content = content.replacingOccurrences(of: searchText, with: replaceWith)
        try TextFileWriter.writeText(to: path, text: content)
        print("Replaced occurrences of '\(searchText)' in: \(path)")
    }

    // Count words in file
    static func countWordsInFile(at path: String) -> Int {
        guard let content = try? TextFileReader.readText(from: path) else {
            return 0
        }

        let words = content.components(separatedBy: .whitespacesAndNewlines)
        let nonEmptyWords = words.filter { !$0.isEmpty }
        return nonEmptyWords.count
    }

    // Read and parse CSV
    static func readCSV(at path: String) -> [[String]] {
        guard let content = try? TextFileReader.readText(from: path) else {
            return []
        }

        return content.components(separatedBy: .newlines).map { line in
            line.components(separatedBy: ",")
        }.filter { !$0.isEmpty }
    }

    // Write JSON to file
    static func writeJSON<T: Encodable>(to path: String, object: T) throws {
        let encoder = JSONEncoder()
        encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
        let data = try encoder.encode(object)

        guard let jsonString = String(data: data, encoding: .utf8) else {
            throw NSError(domain: "JSONError", code: 1, userInfo: [
                NSLocalizedDescriptionKey: "Failed to convert JSON data to string"
            ])
        }

        try TextFileWriter.writeText(to: path, text: jsonString)
        print("JSON written to: \(path)")
    }

    // Read JSON from file
    static func readJSON<T: Decodable>(from path: String, type: T.Type) throws -> T {
        let content = try TextFileReader.readText(from: path)
        guard let data = content.data(using: .utf8) else {
            throw NSError(domain: "JSONError", code: 1, userInfo: [
                NSLocalizedDescriptionKey: "Failed to convert content to data"
            ])
        }

        let decoder = JSONDecoder()
        let result = try decoder.decode(type, from: data)
        print("JSON decoded from: \(path)")
        return result
    }
}

// 5. Safe File Operations with Error Handling
class SafeFileOperations {

    enum FileError: Error, LocalizedError {
        case fileNotFound(String)
        case permissionDenied(String)
        case invalidEncoding
        case writeFailed(String)

        var errorDescription: String? {
            switch self {
            case .fileNotFound(let path):
                return "File not found: \(path)"
            case .permissionDenied(let path):
                return "Permission denied: \(path)"
            case .invalidEncoding:
                return "Invalid file encoding"
            case .writeFailed(let path):
                return "Failed to write to: \(path)"
            }
        }
    }

    // Safe read with comprehensive error handling
    static func safeRead(from path: String) -> Result<String, FileError> {
        guard FileManager.default.fileExists(atPath: path) else {
            return .failure(.fileNotFound(path))
        }

        guard FileManager.default.isReadableFile(atPath: path) else {
            return .failure(.permissionDenied(path))
        }

        do {
            let content = try String(contentsOfFile: path, encoding: .utf8)
            return .success(content)
        } catch {
            return .failure(.invalidEncoding)
        }
    }

    // Safe write with backup
    static func safeWrite(to path: String, text: String, createBackup: Bool = true) -> Result<Void, FileError> {
        // Create backup if requested and file exists
        if createBackup && FileManager.default.fileExists(atPath: path) {
            let backupPath = path + ".backup"
            do {
                try FileManager.default.copyItem(atPath: path, toPath: backupPath)
                print("Backup created at: \(backupPath)")
            } catch {
                return .failure(.writeFailed("Failed to create backup"))
            }
        }

        do {
            try text.write(toFile: path, atomically: true, encoding: .utf8)
            return .success(())
        } catch {
            return .failure(.writeFailed(path))
        }
    }
}

// 6. Character Encoding Handler
class EncodingHandler {

    // Detect file encoding
    static func detectEncoding(at path: String) -> String.Encoding? {
        let encodings: [String.Encoding] = [.utf8, .utf16, .utf16BigEndian, .utf32, .ascii]

        for encoding in encodings {
            if let _ = try? String(contentsOfFile: path, encoding: encoding) {
                return encoding
            }
        }

        return nil
    }

    // Convert file encoding
    static func convertEncoding(at path: String, to targetEncoding: String.Encoding) throws {
        // Read with current encoding
        guard let currentEncoding = detectEncoding(at: path) else {
            throw NSError(domain: "EncodingError", code: 1, userInfo: [
                NSLocalizedDescriptionKey: "Could not detect source encoding"
            ])
        }

        let content = try String(contentsOfFile: path, encoding: currentEncoding)

        // Write with new encoding
        try content.write(toFile: path, atomically: true, encoding: targetEncoding)
        print("Converted encoding from \(currentEncoding) to \(targetEncoding)")
    }
}

// Main demonstration
func demonstrateTextFileOperations() {
    print("=== macOS Swift Text File Read/Write Examples ===\n")

    let testFile = "/tmp/test_text_file.txt"
    let testContent = """
    Hello, World!
    This is a test file.
    Created with Swift on macOS.
    Line 4
    Line 5
    """

    // 1. Basic write
    print("--- 1. Basic Write ---")
    do {
        try TextFileWriter.writeText(to: testFile, text: testContent)
    } catch {
        print("Error writing file: \(error)")
    }

    // 2. Basic read
    print("\n--- 2. Basic Read ---")
    do {
        let content = try TextFileReader.readText(from: testFile)
        print("Content:\n\(content)")
    } catch {
        print("Error reading file: \(error)")
    }

    // 3. Read lines
    print("\n--- 3. Read Lines ---")
    do {
        let lines = try TextFileReader.readLines(from: testFile)
        print("\(lines.count) lines:")
        for (index, line) in lines.enumerated() {
            print("  \(index + 1): \(line)")
        }
    } catch {
        print("Error reading lines: \(error)")
    }

    // 4. Append text
    print("\n--- 4. Append Text ---")
    do {
        try TextFileWriter.appendText(to: testFile, text: "Appended line!")
        let content = try TextFileReader.readText(from: testFile)
        print("Updated content (last line): \(content.components(separatedBy: .newlines).last ?? "")")
    } catch {
        print("Error appending: \(error)")
    }

    // 5. File info
    print("\n--- 5. File Info ---")
    FileInfoHelper.printFileInfo(at: testFile)

    // 6. Word count
    print("\n--- 6. Word Count ---")
    let wordCount = AdvancedTextOperations.countWordsInFile(at: testFile)
    print("Total words: \(wordCount)")

    // 7. Search in file
    print("\n--- 7. Search in File ---")
    let results = AdvancedTextOperations.searchInFile(at: testFile, searchText: "Swift")
    print("Found \(results.count) occurrences of 'Swift':")
    for result in results {
        print("  Line \(result.lineNumber): \(result.line)")
    }

    // 8. JSON operations
    print("\n--- 8. JSON Operations ---")
    struct User: Codable {
        let name: String
        let email: String
        let age: Int
    }

    let user = User(name: "John Doe", email: "[email protected]", age: 30)
    let jsonFile = "/tmp/user.json"

    do {
        try AdvancedTextOperations.writeJSON(to: jsonFile, object: user)
        let decodedUser: User = try AdvancedTextOperations.readJSON(from: jsonFile, type: User.self)
        print("Decoded: \(decodedUser.name) - \(decodedUser.email)")
    } catch {
        print("JSON error: \(error)")
    }

    // 9. Safe operations
    print("\n--- 9. Safe Operations ---")
    let result = SafeFileOperations.safeRead(from: testFile)
    switch result {
    case .success(let content):
        print("Safe read successful: \(content.prefix(50))...")
    case .failure(let error):
        print("Safe read failed: \(error.localizedDescription)")
    }

    // 10. Encoding detection
    print("\n--- 10. Encoding Detection ---")
    if let encoding = EncodingHandler.detectEncoding(at: testFile) {
        print("Detected encoding: \(encoding)")
    }

    print("\n=== All Text File Operations Completed ===")
}

// Run demonstration
demonstrateTextFileOperations()

💻 Dateivalidierung swift

🟢 simple ⭐⭐⭐

Dateiexistenz prüfen, Dateiinformationen abrufen, Dateitypen validieren und Dateien vergleichen

⏱️ 20 min 🏷️ swift, macos, file operations, validation
Prerequisites: Basic Swift knowledge, Foundation framework
// macOS Swift File Validation Examples
// Using Foundation framework

import Foundation

// 1. Basic File Existence Check
class FileChecker {

    // Check if file exists
    static func fileExists(at path: String) -> Bool {
        return FileManager.default.fileExists(atPath: path)
    }

    // Check if path is a file (not directory)
    static func isFile(at path: String) -> Bool {
        var isDirectory: ObjCBool = false
        let exists = FileManager.default.fileExists(atPath: path, isDirectory: &isDirectory)
        return exists && !isDirectory.boolValue
    }

    // Check if path is a directory
    static func isDirectory(at path: String) -> Bool {
        var isDirectory: ObjCBool = false
        let exists = FileManager.default.fileExists(atPath: path, isDirectory: &isDirectory)
        return exists && isDirectory.boolValue
    }

    // Check if file is readable
    static func isReadable(at path: String) -> Bool {
        return FileManager.default.isReadableFile(atPath: path)
    }

    // Check if file is writable
    static func isWritable(at path: String) -> Bool {
        return FileManager.default.isWritableFile(atPath: path)
    }

    // Check if file is deletable
    static func isDeletable(at path: String) -> Bool {
        return FileManager.default.isDeletableFile(atPath: path)
    }

    // Comprehensive file check
    static func checkFile(at path: String) -> FileStatus {
        let fileManager = FileManager.default

        guard fileManager.fileExists(atPath: path) else {
            return FileStatus(status: .notFound, isReadable: false, isWritable: false, isExecutable: false)
        }

        var isDirectory: ObjCBool = false
        fileManager.fileExists(atPath: path, isDirectory: &isDirectory)

        let isReadable = fileManager.isReadableFile(atPath: path)
        let isWritable = fileManager.isWritableFile(atPath: path)
        let isExecutable = fileManager.isExecutableFile(atPath: path)

        let status: FileStatusType = isDirectory.boolValue ? .directory : .file

        return FileStatus(status: status,
                         isReadable: isReadable,
                         isWritable: isWritable,
                         isExecutable: isExecutable)
    }
}

// File Status Types
enum FileStatusType {
    case notFound
    case file
    case directory
    case symbolicLink
}

struct FileStatus {
    let status: FileStatusType
    let isReadable: Bool
    let isWritable: Bool
    let isExecutable: Bool
}

// 2. File Information
class FileInfo {

    // Get complete file attributes
    static func getAttributes(at path: String) -> [FileAttributeKey: Any]? {
        return try? FileManager.default.attributesOfItem(atPath: path)
    }

    // Get file size
    static func getSize(at path: String) -> UInt64? {
        guard let attributes = getAttributes(at: path),
              let size = attributes[.size] as? UInt64 else {
            return nil
        }
        return size
    }

    // Get creation date
    static func getCreationDate(at path: String) -> Date? {
        guard let attributes = getAttributes(at: path),
              let date = attributes[.creationDate] as? Date else {
            return nil
        }
        return date
    }

    // Get modification date
    static func getModificationDate(at path: String) -> Date? {
        guard let attributes = getAttributes(at: path),
              let date = attributes[.modificationDate] as? Date else {
            return nil
        }
        return date
    }

    // Get file extension
    static func getExtension(at path: String) -> String {
        return (path as NSString).pathExtension
    }

    // Get file name without extension
    static func getNameWithoutExtension(at path: String) -> String {
        return (path as NSString).deletingPathExtension
    }

    // Get MIME type
    static func getMIMEType(at path: String) -> String? {
        let extension = getExtension(at: path)
        let uti = UTTypeCreatePreferredIdentifierForTag(
            kUTTagClassFilenameExtension,
            extension as CFString,
            nil
        )?.takeRetainedValue() as String?

        guard let typeID = uti else { return nil }

        return UTTypeCopyPreferredTagWithClass(typeID as CFString, kUTTagClassMIMEType)?.takeRetainedValue() as String?
    }

    // Get detailed file info
    static func getDetailedInfo(at path: String) -> DetailedFileInfo? {
        guard let attributes = getAttributes(at: path) else {
            return nil
        }

        return DetailedFileInfo(
            path: path,
            size: attributes[.size] as? UInt64 ?? 0,
            creationDate: attributes[.creationDate] as? Date,
            modificationDate: attributes[.modificationDate] as? Date,
            fileType: attributes[.type] as? FileAttributeType,
            posixPermissions: attributes[.posixPermissions] as? UInt16
        )
    }
}

// Detailed File Info Structure
struct DetailedFileInfo {
    let path: String
    let size: UInt64
    let creationDate: Date?
    let modificationDate: Date?
    let fileType: FileAttributeType?
    let posixPermissions: UInt16?

    func printInfo() {
        print("\n--- File Information ---")
        print("Path: \(path)")
        print("Size: \(formatSize(size))")

        if let creationDate = creationDate {
            print("Created: \(formatDate(creationDate))")
        }

        if let modificationDate = modificationDate {
            print("Modified: \(formatDate(modificationDate))")
        }

        if let fileType = fileType {
            print("Type: \(fileType.rawValue)")
        }

        if let permissions = posixPermissions {
            print("Permissions: \(String(format: "0%o", permissions))")
        }
    }

    private func formatSize(_ bytes: UInt64) -> String {
        let kb = Double(bytes) / 1024
        let mb = kb / 1024
        let gb = mb / 1024

        if gb >= 1 {
            return String(format: "%.2f GB", gb)
        } else if mb >= 1 {
            return String(format: "%.2f MB", mb)
        } else if kb >= 1 {
            return String(format: "%.2f KB", kb)
        } else {
            return "\(bytes) bytes"
        }
    }

    private func formatDate(_ date: Date) -> String {
        let formatter = DateFormatter()
        formatter.dateStyle = .medium
        formatter.timeStyle = .short
        return formatter.string(from: date)
    }
}

// 3. File Type Validation
class FileTypeValidator {

    // Validate by extension
    static func isValidExtension(at path: String, validExtensions: [String]) -> Bool {
        let ext = ((path as NSString).pathExtension).lowercased()
        return validExtensions.contains(ext)
    }

    // Validate image file
    static func isImageFile(at path: String) -> Bool {
        let imageExtensions = ["jpg", "jpeg", "png", "gif", "bmp", "tiff", "webp", "ico"]
        return isValidExtension(at: path, validExtensions: imageExtensions)
    }

    // Validate text file
    static func isTextFile(at path: String) -> Bool {
        let textExtensions = ["txt", "md", "html", "css", "js", "json", "xml", "csv"]
        return isValidExtension(at: path, validExtensions: textExtensions)
    }

    // Validate by MIME type
    static func hasMIMEType(at path: String, expectedMIME: String) -> Bool {
        guard let mime = FileInfo.getMIMEType(at: path) else {
            return false
        }
        return mime.caseInsensitiveCompare(expectedMIME) == .orderedSame
    }

    // Check if file is empty
    static func isEmpty(at path: String) -> Bool {
        guard let size = FileInfo.getSize(at: path) else {
            return false
        }
        return size == 0
    }

    // Validate file size constraints
    static func isSizeValid(at path: String, minSize: UInt64, maxSize: UInt64) -> Bool {
        guard let size = FileInfo.getSize(at: path) else {
            return false
        }
        return size >= minSize && size <= maxSize
    }
}

// 4. File Comparison
class FileComparator {

    // Compare files by size
    static func compareSize(at path1: String, path2: String) -> ComparisonResult {
        guard let size1 = FileInfo.getSize(at: path1),
              let size2 = FileInfo.getSize(at: path2) else {
            return .error
        }

        if size1 < size2 {
            return .lessThan
        } else if size1 > size2 {
            return .greaterThan
        } else {
            return .equal
        }
    }

    // Compare files by content
    static func compareContent(at path1: String, path2: String) -> Bool {
        guard let data1 = try? Data(contentsOf: URL(fileURLWithPath: path1)),
              let data2 = try? Data(contentsOf: URL(fileURLWithPath: path2)) else {
            return false
        }

        return data1 == data2
    }

    // Compare files by modification date
    static func compareModificationDate(at path1: String, path2: String) -> ComparisonResult {
        guard let date1 = FileInfo.getModificationDate(at: path1),
              let date2 = FileInfo.getModificationDate(at: path2) else {
            return .error
        }

        if date1 < date2 {
            return .lessThan
        } else if date1 > date2 {
            return .greaterThan
        } else {
            return .equal
        }
    }

    // Check if files are identical (size and content)
    static func areIdentical(at path1: String, path2: String) -> Bool {
        return compareSize(at: path1, path2: path2) == .equal &&
               compareContent(at: path1, path2: path2)
    }

    // Compare using checksum
    static func compareChecksum(at path1: String, path2: String) -> Bool {
        guard let hash1 = calculateChecksum(at: path1),
              let hash2 = calculateChecksum(at: path2) else {
            return false
        }
        return hash1 == hash2
    }

    // Calculate file checksum (SHA256)
    static func calculateChecksum(at path: String) -> String? {
        guard let data = try? Data(contentsOf: URL(fileURLWithPath: path)) else {
            return nil
        }

        let hash = data.sha256()
        return hash.map { String(format: "%02x", $0) }.joined()
    }
}

// Comparison Result Enum
enum ComparisonResult {
    case lessThan
    case equal
    case greaterThan
    case error
}

// Data extension for hashing
extension Data {
    func sha256() -> Data {
        var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
        self.withUnsafeBytes {
            _ = CC_SHA256($0.baseAddress, CC_LONG(self.count), &hash)
        }
        return Data(hash)
    }
}

// 5. Path Validation
class PathValidator {

    // Validate path format
    static func isValidPath(_ path: String) -> Bool {
        return !path.isEmpty && (path as NSString).isAbsolutePath
    }

    // Get absolute path from relative
    static func getAbsolutePath(_ path: String) -> String? {
        let fileManager = FileManager.default
        return fileManager.absolutePath(forPath: path)
    }

    // Resolve path with tilde
    static func resolveTilde(_ path: String) -> String {
        return (path as NSString).expandingTildeInPath
    }

    // Validate file name
    static func isValidFileName(_ name: String) -> Bool {
        // Check for invalid characters
        let invalidChars = CharacterSet(charactersIn: "\/:*?"<>|")
        return name.rangeOfCharacter(from: invalidChars) == nil && !name.isEmpty
    }

    // Sanitize file name
    static func sanitizeFileName(_ name: String) -> String {
        let invalidChars = CharacterSet(charactersIn: "\/:*?"<>|")
        return name.components(separatedBy: invalidChars).joined(separator: "_")
    }
}

// 6. File Integrity Checker
class FileIntegrityChecker {

    // Verify file hasn't been corrupted using stored hash
    static func verifyIntegrity(at path: String, against expectedHash: String) -> Bool {
        guard let actualHash = FileComparator.calculateChecksum(at: path) else {
            return false
        }
        return actualHash.lowercased() == expectedHash.lowercased()
    }

    // Generate hash file for integrity checking
    static func generateHashFile(at path: String) -> String? {
        return FileComparator.calculateChecksum(at: path)
    }

    // Quick check (just size)
    static func quickCheck(at path: String, expectedSize: UInt64) -> Bool {
        guard let actualSize = FileInfo.getSize(at: path) else {
            return false
        }
        return actualSize == expectedSize
    }
}

// Main demonstration
func demonstrateFileValidation() {
    print("=== macOS Swift File Validation Examples ===\n")

    let testFile = "/tmp/validation_test.txt"
    let testDir = "/tmp/validation_test_dir"

    // Create test file
    let fileManager = FileManager.default
    try? "Test content for validation".write(toFile: testFile, atomically: true, encoding: .utf8)
    try? fileManager.createDirectory(atPath: testDir, withIntermediateDirectories: true)

    // 1. File existence checks
    print("--- 1. File Existence Checks ---")
    print("File exists: \(FileChecker.fileExists(at: testFile))")
    print("Is file: \(FileChecker.isFile(at: testFile))")
    print("Is directory: \(FileChecker.isDirectory(at: testDir))")
    print("Is readable: \(FileChecker.isReadable(at: testFile))")
    print("Is writable: \(FileChecker.isWritable(at: testFile))")

    // 2. Comprehensive file check
    print("\n--- 2. Comprehensive File Check ---")
    let status = FileChecker.checkFile(at: testFile)
    print("Status: \(status.status)")
    print("Readable: \(status.isReadable)")
    print("Writable: \(status.isWritable)")
    print("Executable: \(status.isExecutable)")

    // 3. File information
    print("\n--- 3. File Information ---")
    if let size = FileInfo.getSize(at: testFile) {
        print("Size: \(size) bytes")
    }
    if let modDate = FileInfo.getModificationDate(at: testFile) {
        print("Modified: \(modDate)")
    }
    print("Extension: \(FileInfo.getExtension(at: testFile))")
    print("Name without ext: \(FileInfo.getNameWithoutExtension(at: testFile))")

    // 4. Detailed info
    print("\n--- 4. Detailed File Info ---")
    if let info = FileInfo.getDetailedInfo(at: testFile) {
        info.printInfo()
    }

    // 5. File type validation
    print("\n--- 5. File Type Validation ---")
    print("Is text file: \(FileTypeValidator.isTextFile(at: testFile))")
    print("Is image file: \(FileTypeValidator.isImageFile(at: testFile))")
    print("Is empty: \(FileTypeValidator.isEmpty(at: testFile))")
    print("Size valid (1-1000 bytes): \(FileTypeValidator.isSizeValid(at: testFile, minSize: 1, maxSize: 1000))")

    // 6. File comparison
    print("\n--- 6. File Comparison ---")
    let testFile2 = "/tmp/validation_test2.txt"
    try? "Different content".write(toFile: testFile2, atomically: true, encoding: .utf8)

    let sizeCompare = FileComparator.compareSize(at: testFile, path2: testFile2)
    print("Size comparison: \(sizeCompare)")

    let contentEqual = FileComparator.compareContent(at: testFile, path2: testFile)
    print("Content equal: \(contentEqual)")

    // 7. Checksum
    print("\n--- 7. Checksum ---")
    if let checksum = FileComparator.calculateChecksum(at: testFile) {
        print("SHA256: \(checksum)")

        // Verify integrity
        let valid = FileIntegrityChecker.verifyIntegrity(at: testFile, against: checksum)
        print("Integrity check: \(valid ? "PASSED" : "FAILED")")
    }

    // 8. Path validation
    print("\n--- 8. Path Validation ---")
    let relativePath = "./test.txt"
    print("Is absolute path: \(PathValidator.isValidPath(testFile))")
    print("Resolved absolute path: \(PathValidator.getAbsolutePath(relativePath) ?? "None")")
    print("Valid filename 'test.txt': \(PathValidator.isValidFileName("test.txt"))")
    print("Valid filename 'test?.txt': \(PathValidator.isValidFileName("test?.txt"))")
    print("Sanitized name: \(PathValidator.sanitizeFileName("test?.txt"))")

    // Cleanup
    try? fileManager.removeItem(atPath: testFile)
    try? fileManager.removeItem(atPath: testFile2)
    try? fileManager.removeItem(atPath: testDir)
    print("\nCleanup completed")

    print("\n=== All File Validation Examples Completed ===")
}

// Run demonstration
demonstrateFileValidation()

💻 Dateien Kopieren/Verschieben swift

🟡 intermediate ⭐⭐⭐

Dateien mit Überschreibungsoptionen, Fortschrittsverfolgung und Fehlerwiederherstellung kopieren und verschieben

⏱️ 25 min 🏷️ swift, macos, file operations
Prerequisites: Basic Swift knowledge, Foundation framework
// macOS Swift File Copy/Move Examples
// Using Foundation framework

import Foundation

// 1. Basic File Copy
class FileCopier {

    // Simple copy
    static func copyFile(from source: String, to destination: String) throws {
        try FileManager.default.copyItem(atPath: source, toPath: destination)
        print("Copied: \(source) -> \(destination)")
    }

    // Copy with overwrite option
    static func copyFile(from source: String, to destination: String, overwrite: Bool) throws {
        let fileManager = FileManager.default

        // Check if destination exists
        if fileManager.fileExists(atPath: destination) {
            if overwrite {
                // Remove existing file
                try fileManager.removeItem(atPath: destination)
                print("Removed existing file: \(destination)")
            } else {
                throw FileError.fileAlreadyExists(destination)
            }
        }

        try copyFile(from: source, to: destination)
    }

    // Copy to directory
    static func copyFileToDirectory(from source: String, directory: String) throws {
        let fileName = (source as NSString).lastPathComponent
        let destination = (directory as NSString).appendingPathComponent(fileName)
        try copyFile(from: source, to: destination)
    }

    // Copy with URL
    static func copyFile(from sourceURL: URL, to destinationURL: URL) throws {
        let fileManager = FileManager.default

        // Create destination directory if needed
        let destDir = destinationURL.deletingLastPathComponent().path
        if !fileManager.fileExists(atPath: destDir) {
            try fileManager.createDirectory(atPath: destDir, withIntermediateDirectories: true)
        }

        try fileManager.copyItem(at: sourceURL, to: destinationURL)
        print("Copied: \(sourceURL.path) -> \(destinationURL.path)")
    }

    // Copy with progress callback
    static func copyFileWithProgress(from source: String, to destination: String,
                                     progress: ((Double) -> Void)?) throws {
        let fileManager = FileManager.default

        guard fileManager.fileExists(atPath: source) else {
            throw FileError.fileNotFound(source)
        }

        let attributes = try fileManager.attributesOfItem(atPath: source)
        guard let fileSize = attributes[.size] as? UInt64 else {
            throw FileError.invalidFile
        }

        // Read source in chunks
        guard let sourceHandle = FileHandle(forReadingAtPath: source) else {
            throw FileError.readFailed(source)
        }

        // Create destination
        fileManager.createFile(atPath: destination, contents: nil)
        guard let destHandle = FileHandle(forWritingAtPath: destination) else {
            throw FileError.writeFailed(destination)
        }

        let chunkSize = 1024 * 1024 // 1MB chunks
        var bytesCopied: UInt64 = 0

        defer {
            sourceHandle.closeFile()
            destHandle.closeFile()
        }

        while true {
            let data = sourceHandle.readData(ofLength: chunkSize)
            if data.isEmpty { break }

            destHandle.write(data)
            bytesCopied += UInt64(data.count)

            let percent = Double(bytesCopied) / Double(fileSize)
            progress?(percent)
        }

        print("Copy completed: \(destination)")
    }
}

// 2. Basic File Move
class FileMover {

    // Simple move
    static func moveFile(from source: String, to destination: String) throws {
        try FileManager.default.moveItem(atPath: source, toPath: destination)
        print("Moved: \(source) -> \(destination)")
    }

    // Move with overwrite
    static func moveFile(from source: String, to destination: String, overwrite: Bool) throws {
        let fileManager = FileManager.default

        if fileManager.fileExists(atPath: destination) {
            if overwrite {
                try fileManager.removeItem(atPath: destination)
                print("Removed existing file: \(destination)")
            } else {
                throw FileError.fileAlreadyExists(destination)
            }
        }

        try moveFile(from: source, to: destination)
    }

    // Move to directory
    static func moveFileToDirectory(from source: String, directory: String) throws {
        let fileName = (source as NSString).lastPathComponent
        let destination = (directory as NSString).appendingPathComponent(fileName)
        try moveFile(from: source, to: destination)
    }

    // Safe move with backup
    static func moveFileWithBackup(from source: String, to destination: String) throws {
        let fileManager = FileManager.default

        // Create backup if destination exists
        if fileManager.fileExists(atPath: destination) {
            let backupPath = destination + ".backup"
            try fileManager.moveItem(atPath: destination, toPath: backupPath)
            print("Backup created: \(backupPath)")
        }

        try moveFile(from: source, to: destination)
    }

    // Move with URL
    static func moveFile(from sourceURL: URL, to destinationURL: URL) throws {
        let fileManager = FileManager.default

        // Create destination directory if needed
        let destDir = destinationURL.deletingLastPathComponent().path
        if !fileManager.fileExists(atPath: destDir) {
            try fileManager.createDirectory(atPath: destDir, withIntermediateDirectories: true)
        }

        try fileManager.moveItem(at: sourceURL, to: destinationURL)
        print("Moved: \(sourceURL.path) -> \(destinationURL.path)")
    }
}

// 3. Batch Operations
class BatchFileOperations {

    // Copy multiple files
    static func copyFiles(sources: [String], to destinationDirectory: String) throws {
        let fileManager = FileManager.default

        // Ensure destination directory exists
        if !fileManager.fileExists(atPath: destinationDirectory) {
            try fileManager.createDirectory(atPath: destinationDirectory,
                                           withIntermediateDirectories: true)
        }

        var successCount = 0
        var failureCount = 0

        for source in sources {
            do {
                let fileName = (source as NSString).lastPathComponent
                let destination = (destinationDirectory as NSString).appendingPathComponent(fileName)
                try FileCopier.copyFile(from: source, to: destination, overwrite: true)
                successCount += 1
            } catch {
                print("Failed to copy \(source): \(error)")
                failureCount += 1
            }
        }

        print("Batch copy completed: \(successCount) succeeded, \(failureCount) failed")
    }

    // Move multiple files
    static func moveFiles(sources: [String], to destinationDirectory: String) throws {
        let fileManager = FileManager.default

        if !fileManager.fileExists(atPath: destinationDirectory) {
            try fileManager.createDirectory(atPath: destinationDirectory,
                                           withIntermediateDirectories: true)
        }

        var successCount = 0
        var failureCount = 0

        for source in sources {
            do {
                let fileName = (source as NSString).lastPathComponent
                let destination = (destinationDirectory as NSString).appendingPathComponent(fileName)
                try FileMover.moveFile(from: source, to: destination, overwrite: true)
                successCount += 1
            } catch {
                print("Failed to move \(source): \(error)")
                failureCount += 1
            }
        }

        print("Batch move completed: \(successCount) succeeded, \(failureCount) failed")
    }

    // Copy directory recursively
    static func copyDirectory(from source: String, to destination: String) throws {
        let fileManager = FileManager.default

        var isDirectory: ObjCBool = false
        guard fileManager.fileExists(atPath: source, isDirectory: &isDirectory),
              isDirectory.boolValue else {
            throw FileError.notADirectory(source)
        }

        try fileManager.copyItem(atPath: source, toPath: destination)
        print("Directory copied: \(source) -> \(destination)")
    }

    // Move directory
    static func moveDirectory(from source: String, to destination: String) throws {
        let fileManager = FileManager.default

        var isDirectory: ObjCBool = false
        guard fileManager.fileExists(atPath: source, isDirectory: &isDirectory),
              isDirectory.boolValue else {
            throw FileError.notADirectory(source)
        }

        try fileManager.moveItem(atPath: source, toPath: destination)
        print("Directory moved: \(source) -> \(destination)")
    }
}

// 4. File Error Types
enum FileError: Error, LocalizedError {
    case fileNotFound(String)
    case fileAlreadyExists(String)
    case permissionDenied(String)
    case notADirectory(String)
    case invalidFile
    case readFailed(String)
    case writeFailed(String)

    var errorDescription: String? {
        switch self {
        case .fileNotFound(let path):
            return "File not found: \(path)"
        case .fileAlreadyExists(let path):
            return "File already exists: \(path)"
        case .permissionDenied(let path):
            return "Permission denied: \(path)"
        case .notADirectory(let path):
            return "Not a directory: \(path)"
        case .invalidFile:
            return "Invalid file"
        case .readFailed(let path):
            return "Failed to read: \(path)"
        case .writeFailed(let path):
            return "Failed to write: \(path)"
        }
    }
}

// 5. Smart File Operations
class SmartFileOperations {

    // Copy with duplicate handling
    static func smartCopy(from source: String, to destination: String) throws {
        let fileManager = FileManager.default

        if fileManager.fileExists(atPath: destination) {
            // Add number suffix
            let baseName = (destination as NSString).deletingPathExtension
            let extensionName = (destination as NSString).pathExtension

            var counter = 1
            var newPath = destination

            while fileManager.fileExists(atPath: newPath) {
                let newBaseName = "\(baseName) \(counter)"
                newPath = (newBaseName as NSString).appendingPathExtension(extensionName) ?? newBaseName
                counter += 1
            }

            print("Destination exists, using: \(newPath)")
            try FileCopier.copyFile(from: source, to: newPath)
        } else {
            try FileCopier.copyFile(from: source, to: destination)
        }
    }

    // Safe move with undo
    static func moveWithUndo(from source: String, to destination: String) throws -> () -> Void {
        let fileManager = FileManager.default

        // Remember original location for undo
        let originalSource = source

        if fileManager.fileExists(atPath: destination) {
            try fileManager.removeItem(atPath: destination)
        }

        try FileMover.moveFile(from: source, to: destination)

        // Return undo function
        return {
            do {
                try FileMover.moveFile(from: destination, to: originalSource)
                print("Undo: Moved back to \(originalSource)")
            } catch {
                print("Undo failed: \(error)")
            }
        }
    }

    // Copy with file verification
    static func verifiedCopy(from source: String, to destination: String) throws {
        let sourceAttrs = FileManager.default.attributesOfItem(atPath: source)

        try FileCopier.copyFile(from: source, to: destination, overwrite: true)

        // Verify by comparing file sizes
        let destAttrs = FileManager.default.attributesOfItem(atPath: destination)

        guard let sourceSize = sourceAttrs[.size] as? UInt64,
              let destSize = destAttrs[.size] as? UInt64,
              sourceSize == destSize else {
            throw FileError.writeFailed(destination)
        }

        print("Verified copy: \(sourceSize) bytes")
    }
}

// 6. File Operation with Attributes
class FileOperationWithAttributes {

    // Copy preserving attributes
    static func copyWithAttributes(from source: String, to destination: String) throws {
        let fileManager = FileManager.default

        // Get source attributes
        guard let attributes = try? fileManager.attributesOfItem(atPath: source) else {
            throw FileError.invalidFile
        }

        // Copy file
        try FileCopier.copyFile(from: source, to: destination, overwrite: true)

        // Apply attributes
        try fileManager.setAttributes(attributes, ofItemAtPath: destination)

        print("Copied with attributes preserved")
    }

    // Copy with permission change
    static func copyWithPermissions(from source: String, to destination: String,
                                    permissions: FilePermissions) throws {
        try FileCopier.copyFile(from: source, to: destination, overwrite: true)

        let fileManager = FileManager.default
        try fileManager.setAttributes([.posixPermissions: permissions.rawValue],
                                     ofItemAtPath: destination)

        print("Copied with permissions: \(permissions.rawValue)")
    }
}

// Main demonstration
func demonstrateFileCopyMove() {
    print("=== macOS Swift File Copy/Move Examples ===\n")

    let tempDir = "/tmp/file_operations_test"
    let sourceFile = "/tmp/source_test.txt"
    let destFile1 = "/tmp/dest_test1.txt"
    let destFile2 = "/tmp/dest_test2.txt"

    // Create test file
    let fileManager = FileManager.default
    try? fileManager.createDirectory(atPath: tempDir, withIntermediateDirectories: true)

    try? "Test content for copy/move".write(toFile: sourceFile, atomically: true, encoding: .utf8)

    // 1. Simple copy
    print("--- 1. Simple Copy ---")
    do {
        try FileCopier.copyFile(from: sourceFile, to: destFile1)
    } catch {
        print("Error: \(error)")
    }

    // 2. Copy with progress
    print("\n--- 2. Copy with Progress ---")
    do {
        try FileCopier.copyFileWithProgress(from: sourceFile, to: destFile2) { progress in
            print("Progress: \(Int(progress * 100))%")
        }
    } catch {
        print("Error: \(error)")
    }

    // 3. Simple move
    print("\n--- 3. Simple Move ---")
    let moveSource = "/tmp/move_source.txt"
    let moveDest = "/tmp/move_dest.txt"
    try? "File to move".write(toFile: moveSource, atomically: true, encoding: .utf8)

    do {
        try FileMover.moveFile(from: moveSource, to: moveDest)
    } catch {
        print("Error: \(error)")
    }

    // 4. Smart copy (handle duplicates)
    print("\n--- 4. Smart Copy ---")
    let smartSource = "/tmp/smart_source.txt"
    let smartDest = "/tmp/smart_dest.txt"
    try? "Smart copy test".write(toFile: smartSource, atomically: true, encoding: .utf8)

    do {
        try SmartFileOperations.smartCopy(from: smartSource, to: smartDest)
        try SmartFileOperations.smartCopy(from: smartSource, to: smartDest) // Will create duplicate
    } catch {
        print("Error: \(error)")
    }

    // 5. Batch copy
    print("\n--- 5. Batch Copy ---")
    let files = (1...3).map { "/tmp/batch_source\($0).txt" }
    files.forEach { try? "Batch file \($0)".write(toFile: $0, atomically: true, encoding: .utf8) }

    do {
        try BatchFileOperations.copyFiles(sources: files, to: tempDir)
    } catch {
        print("Error: \(error)")
    }

    // 6. Verified copy
    print("\n--- 6. Verified Copy ---")
    let verifySource = "/tmp/verify_source.txt"
    let verifyDest = "/tmp/verify_dest.txt"
    try? "Verification test".write(toFile: verifySource, atomically: true, encoding: .utf8)

    do {
        try SmartFileOperations.verifiedCopy(from: verifySource, to: verifyDest)
    } catch {
        print("Error: \(error)")
    }

    // 7. Move with undo
    print("\n--- 7. Move with Undo ---")
    let undoSource = "/tmp/undo_source.txt"
    let undoDest = "/tmp/undo_dest.txt"
    try? "Undo test".write(toFile: undoSource, atomically: true, encoding: .utf8)

    do {
        let undo = try SmartFileOperations.moveWithUndo(from: undoSource, to: undoDest)
        print("File moved, executing undo...")
        undo()
    } catch {
        print("Error: \(error)")
    }

    // Cleanup
    try? fileManager.removeItem(atPath: tempDir)
    print("\nCleanup completed")

    print("\n=== All File Copy/Move Examples Completed ===")
}

// Run demonstration
demonstrateFileCopyMove()

💻 Verzeichnisdurchlauf swift

🟡 intermediate ⭐⭐⭐⭐

Verzeichnisse rekursiv durchlaufen, Dateien mit Filtern auflisten und bestimmte Dateitypen suchen

⏱️ 30 min 🏷️ swift, macos, file operations, directory
Prerequisites: Intermediate Swift, Foundation framework
// macOS Swift Directory Traversal Examples
// Using Foundation framework

import Foundation

// 1. Basic Directory Listing
class DirectoryLister {

    // List all items in directory
    static func listDirectory(at path: String) throws -> [String] {
        let fileManager = FileManager.default

        guard let contents = try? fileManager.contentsOfDirectory(atPath: path) else {
            throw DirectoryError.notADirectory(path)
        }

        return contents
    }

    // List with details
    static func listDirectoryWithDetails(at path: String) throws -> [FileItem] {
        let fileManager = FileManager.default
        var items: [FileItem] = []

        guard let contents = try? fileManager.contentsOfDirectory(atPath: path) else {
            throw DirectoryError.notADirectory(path)
        }

        for item in contents {
            let itemPath = (path as NSString).appendingPathComponent(item)
            let isDirectory = (try? itemPath.isDirectory()) ?? false

            var fileItem = FileItem(name: item, path: itemPath, isDirectory: isDirectory)

            if let attributes = try? fileManager.attributesOfItem(atPath: itemPath) {
                fileItem.size = attributes[.size] as? UInt64 ?? 0
                fileItem.modifiedDate = attributes[.modificationDate] as? Date
            }

            items.append(fileItem)
        }

        return items
    }

    // List only files
    static func listFiles(at path: String) throws -> [String] {
        let contents = try listDirectory(path)
        return contents.filter { item in
            let itemPath = (path as NSString).appendingPathComponent(item)
            var isDirectory: ObjCBool = false
            FileManager.default.fileExists(atPath: itemPath, isDirectory: &isDirectory)
            return !isDirectory.boolValue
        }
    }

    // List only subdirectories
    static func listSubdirectories(at path: String) throws -> [String] {
        let contents = try listDirectory(path)
        return contents.filter { item in
            let itemPath = (path as NSString).appendingPathComponent(item)
            var isDirectory: ObjCBool = false
            FileManager.default.fileExists(atPath: itemPath, isDirectory: &isDirectory)
            return isDirectory.boolValue
        }
    }
}

// File Item Structure
struct FileItem {
    let name: String
    let path: String
    let isDirectory: Bool
    var size: UInt64 = 0
    var modifiedDate: Date?
}

// Directory Error Types
enum DirectoryError: Error, LocalizedError {
    case notADirectory(String)
    case directoryNotFound(String)
    case accessDenied(String)

    var errorDescription: String? {
        switch self {
        case .notADirectory(let path):
            return "Not a directory: \(path)"
        case .directoryNotFound(let path):
            return "Directory not found: \(path)"
        case .accessDenied(let path):
            return "Access denied: \(path)"
        }
    }
}

// 2. Recursive Directory Traversal
class DirectoryTraverser {

    // Recursively find all files
    static func findAllFiles(at path: String) -> [String] {
        var files: [String] = []
        let fileManager = FileManager.default

        guard let contents = try? fileManager.contentsOfDirectory(atPath: path) else {
            return files
        }

        for item in contents {
            let itemPath = (path as NSString).appendingPathComponent(item)
            var isDirectory: ObjCBool = false

            if fileManager.fileExists(atPath: itemPath, isDirectory: &isDirectory) {
                if isDirectory.boolValue {
                    // Recurse into subdirectory
                    files.append(contentsOf: findAllFiles(at: itemPath))
                } else {
                    files.append(itemPath)
                }
            }
        }

        return files
    }

    // Recursive traversal with callback
    static func traverseDirectory(at path: String,
                                  callback: (String, Bool, Int) -> Void) {
        traverseDirectory(at: path, depth: 0, callback: callback)
    }

    private static func traverseDirectory(at path: String, depth: Int,
                                          callback: (String, Bool, Int) -> Void) {
        let fileManager = FileManager.default

        guard let contents = try? fileManager.contentsOfDirectory(atPath: path) else {
            return
        }

        for item in contents {
            let itemPath = (path as NSString).appendingPathComponent(item)
            var isDirectory: ObjCBool = false

            if fileManager.fileExists(atPath: itemPath, isDirectory: &isDirectory) {
                callback(itemPath, isDirectory.boolValue, depth)

                if isDirectory.boolValue {
                    traverseDirectory(at: itemPath, depth: depth + 1, callback: callback)
                }
            }
        }
    }

    // Get directory tree
    static func getDirectoryTree(at path: String, maxDepth: Int = Int.max) -> DirectoryNode {
        let root = DirectoryNode(name: (path as NSString).lastPathComponent,
                                path: path,
                                isDirectory: true,
                                depth: 0)
        buildTree(for: root, maxDepth: maxDepth)
        return root
    }

    private static func buildTree(for node: DirectoryNode, maxDepth: Int) {
        guard node.depth < maxDepth else { return }

        let fileManager = FileManager.default

        guard let contents = try? fileManager.contentsOfDirectory(atPath: node.path) else {
            return
        }

        for item in contents.sorted() {
            let itemPath = (node.path as NSString).appendingPathComponent(item)
            var isDirectory: ObjCBool = false

            if fileManager.fileExists(atPath: itemPath, isDirectory: &isDirectory) {
                let childNode = DirectoryNode(name: item,
                                             path: itemPath,
                                             isDirectory: isDirectory.boolValue,
                                             depth: node.depth + 1)
                node.children.append(childNode)

                if isDirectory.boolValue {
                    buildTree(for: childNode, maxDepth: maxDepth)
                }
            }
        }
    }
}

// Directory Tree Node
class DirectoryNode {
    let name: String
    let path: String
    let isDirectory: Bool
    let depth: Int
    var children: [DirectoryNode] = []

    init(name: String, path: String, isDirectory: Bool, depth: Int) {
        self.name = name
        self.path = path
        self.isDirectory = isDirectory
        self.depth = depth
    }

    func printTree() {
        let indent = String(repeating: "  ", count: depth)
        let prefix = isDirectory ? "📁" : "📄"
        print("\(indent)\(prefix) \(name)")
        for child in children {
            child.printTree()
        }
    }
}

// 3. File Filtering
class FileFilter {

    // Filter by extension
    static func filterByExtension(in path: String, extensions: [String]) -> [String] {
        let files = DirectoryTraverser.findAllFiles(at: path)

        return files.filter { filePath in
            let ext = (filePath as NSString).pathExtension.lowercased()
            return extensions.contains(ext)
        }
    }

    // Filter by name pattern
    static func filterByNamePattern(in path: String, pattern: String) -> [String] {
        let files = DirectoryTraverser.findAllFiles(at: path)

        return files.filter { filePath in
            let fileName = (filePath as NSString).lastPathComponent
            return fileName.range(of: pattern, options: .regularExpression) != nil
        }
    }

    // Filter by size
    static func filterBySize(in path: String, minSize: UInt64, maxSize: UInt64) -> [String] {
        let fileManager = FileManager.default
        let files = DirectoryTraverser.findAllFiles(at: path)

        return files.filter { filePath in
            guard let attributes = try? fileManager.attributesOfItem(atPath: filePath),
                  let size = attributes[.size] as? UInt64 else {
                return false
            }
            return size >= minSize && size <= maxSize
        }
    }

    // Filter by date
    static func filterByModifiedDate(in path: String,
                                     after startDate: Date,
                                     before endDate: Date) -> [String] {
        let fileManager = FileManager.default
        let files = DirectoryTraverser.findAllFiles(at: path)

        return files.filter { filePath in
            guard let attributes = try? fileManager.attributesOfItem(atPath: filePath),
                  let modifiedDate = attributes[.modificationDate] as? Date else {
                return false
            }
            return modifiedDate >= startDate && modifiedDate <= endDate
        }
    }

    // Find duplicates by size
    static func findPotentialDuplicates(in path: String) -> [[String]] {
        let fileManager = FileManager.default
        let files = DirectoryTraverser.findAllFiles(at: path)

        var sizeGroups: [UInt64: [String]] = [:]

        for filePath in files {
            guard let attributes = try? fileManager.attributesOfItem(atPath: filePath),
                  let size = attributes[.size] as? UInt64 else {
                continue
            }

            if sizeGroups[size] == nil {
                sizeGroups[size] = []
            }
            sizeGroups[size]?.append(filePath)
        }

        // Return groups with more than one file
        return sizeGroups.values.filter { $0.count > 1 }
    }
}

// 4. Directory Statistics
class DirectoryStatistics {

    struct Stats {
        var totalFiles: Int = 0
        var totalDirectories: Int = 0
        var totalSize: UInt64 = 0
        var largestFile: (path: String, size: UInt64)?
        var extensionCounts: [String: Int] = [:]
    }

    static func calculateStatistics(for path: String) -> Stats {
        var stats = Stats()

        DirectoryTraverser.traverseDirectory(at: path) { filePath, isDirectory, _ in
            if isDirectory {
                stats.totalDirectories += 1
            } else {
                stats.totalFiles += 1

                let fileManager = FileManager.default
                if let attributes = try? fileManager.attributesOfItem(atPath: filePath),
                   let size = attributes[.size] as? UInt64 {
                    stats.totalSize += size

                    // Track largest file
                    if stats.largestFile == nil || size > stats.largestFile!.size {
                        stats.largestFile = (filePath, size)
                    }

                    // Count extensions
                    let ext = ((filePath as NSString).pathExtension).lowercased()
                    let extKey = ext.isEmpty ? "(no extension)" : ext
                    stats.extensionCounts[extKey, default: 0] += 1
                }
            }
        }

        return stats
    }

    static func printStatistics(_ stats: Stats) {
        print("\n=== Directory Statistics ===")
        print("Total files: \(stats.totalFiles)")
        print("Total directories: \(stats.totalDirectories)")
        print("Total size: \(formatBytes(stats.totalSize))")

        if let largest = stats.largestFile {
            print("Largest file: \((largest.path as NSString).lastPathComponent)")
            print("  Size: \(formatBytes(largest.size))")
        }

        print("\nExtension counts:")
        for (ext, count) in stats.extensionCounts.sorted(by: { $0.value > $1.value }) {
            print("  .\(ext): \(count)")
        }
    }

    private static func formatBytes(_ bytes: UInt64) -> String {
        let kb = Double(bytes) / 1024
        let mb = kb / 1024
        let gb = mb / 1024

        if gb >= 1 {
            return String(format: "%.2f GB", gb)
        } else if mb >= 1 {
            return String(format: "%.2f MB", mb)
        } else if kb >= 1 {
            return String(format: "%.2f KB", kb)
        } else {
            return "\(bytes) bytes"
        }
    }
}

// 5. File Searcher
class FileSearcher {

    // Search files by name
    static func searchByName(in path: String, name: String) -> [String] {
        let files = DirectoryTraverser.findAllFiles(at: path)

        return files.filter { filePath in
            let fileName = (filePath as NSString).lastPathComponent
            return fileName.range(of: name, options: .caseInsensitive) != nil
        }
    }

    // Search files containing text
    static func searchByContent(in path: String, searchText: String) -> [String] {
        let files = DirectoryTraverser.findAllFiles(at: path)
        var matches: [String] = []

        for filePath in files {
            if let content = try? String(contentsOfFile: filePath, encoding: .utf8) {
                if content.range(of: searchText, options: .caseInsensitive) != nil {
                    matches.append(filePath)
                }
            }
        }

        return matches
    }

    // Find recently modified files
    static func findRecentlyModified(in path: String, within seconds: TimeInterval) -> [String] {
        let fileManager = FileManager.default
        let files = DirectoryTraverser.findAllFiles(at: path)
        let cutoffDate = Date().addingTimeInterval(-seconds)

        return files.filter { filePath in
            guard let attributes = try? fileManager.attributesOfItem(atPath: filePath),
                  let modifiedDate = attributes[.modificationDate] as? Date else {
                return false
            }
            return modifiedDate > cutoffDate
        }
    }
}

// 6. Path Helper Extension
extension String {

    func isDirectory() throws -> Bool {
        var isDirectory: ObjCBool = false
        FileManager.default.fileExists(atPath: self, isDirectory: &isDirectory)
        return isDirectory.boolValue
    }

    var fileExists: Bool {
        FileManager.default.fileExists(atPath: self)
    }
}

// Main demonstration
func demonstrateDirectoryTraversal() {
    print("=== macOS Swift Directory Traversal Examples ===\n")

    let testDir = "/tmp/directory_traversal_test"
    let fileManager = FileManager.default

    // Create test directory structure
    try? fileManager.createDirectory(atPath: testDir, withIntermediateDirectories: true)

    // Create some test files
    try? "File 1".write(toFile: "\(testDir)/file1.txt", atomically: true, encoding: .utf8)
    try? "File 2".write(toFile: "\(testDir)/file2.md", atomically: true, encoding: .utf8)

    // Create subdirectory
    let subDir = "\(testDir)/subdir"
    try? fileManager.createDirectory(atPath: subDir, withIntermediateDirectories: true)
    try? "Subfile 1".write(toFile: "\(subDir)/subfile1.txt", atomically: true, encoding: .utf8)

    // 1. List directory
    print("--- 1. List Directory ---")
    do {
        let items = try DirectoryLister.listDirectory(at: testDir)
        print("Items in \(testDir):")
        for item in items {
            print("  - \(item)")
        }
    } catch {
        print("Error: \(error)")
    }

    // 2. List with details
    print("\n--- 2. List with Details ---")
    do {
        let items = try DirectoryLister.listDirectoryWithDetails(at: testDir)
        print("Files in \(testDir):")
        for item in items {
            let type = item.isDirectory ? "DIR " : "FILE"
            print("  [\(type)] \(item.name) - \(item.size) bytes")
        }
    } catch {
        print("Error: \(error)")
    }

    // 3. Recursive traversal
    print("\n--- 3. Recursive Traversal ---")
    let allFiles = DirectoryTraverser.findAllFiles(at: testDir)
    print("All files:")
    for file in allFiles {
        print("  - \(file)")
    }

    // 4. Directory tree
    print("\n--- 4. Directory Tree ---")
    let tree = DirectoryTraverser.getDirectoryTree(at: testDir, maxDepth: 2)
    tree.printTree()

    // 5. Filter by extension
    print("\n--- 5. Filter by Extension ---")
    let txtFiles = FileFilter.filterByExtension(in: testDir, extensions: ["txt"])
    print("Text files:")
    for file in txtFiles {
        print("  - \(file)")
    }

    // 6. Directory statistics
    print("\n--- 6. Directory Statistics ---")
    let stats = DirectoryStatistics.calculateStatistics(for: testDir)
    DirectoryStatistics.printStatistics(stats)

    // 7. Search by name
    print("\n--- 7. Search by Name ---")
    let searchResults = FileSearcher.searchByName(in: testDir, name: "file")
    print("Files containing 'file':")
    for result in searchResults {
        print("  - \(result)")
    }

    // Cleanup
    try? fileManager.removeItem(atPath: testDir)
    print("\nCleanup completed")

    print("\n=== All Directory Traversal Examples Completed ===")
}

// Run demonstration
demonstrateDirectoryTraversal()