肇鑫的技术博客

业精于勤,荒于嬉

Dealing with Filenames that contain "/" in macOS

My app crashed when I saved a file to disk. The reason was that the filename was "Poster 2/咕唧2.json". Although you can use "/" in a filename that in Finder. macOS uses "/" as the separator between directories and filenames. When the app ran, macOS tried to find a filename "咕唧2.json" under "Poster 2" directory, instead of finding a file named "Poster 2/咕唧2.json".

Finder uses ":" and Terminal uses "/"

You need to replace the "/" in filenames to ":". And Finder will read it show them as "/". So when writing, use

appInfos.forEach {
    let jsonData = getJsonData(from: $0)
    var filename = $0.name
    replaceSlashWithColon(&filename)
    let outputURL = URL(fileURLWithPath: filename + ".json", isDirectory: false, relativeTo: subFolder)
    try! jsonData.write(to: outputURL)
}
            
private func replaceSlashWithColon(_ str:inout String) {
    str = str.replacingOccurrences(of: "/", with: ":")
}

When reading:

appInfos = fileList.map({ name, version -> AppInfo in
    var filename = name
    replaceSlashWithColon(&filename)
    let url = URL(fileURLWithPath: filename + ".json", isDirectory: false, relativeTo: subfolder)
    let jsonData = try! Data(contentsOf: url)
    return try! decoder.decode(AppInfo.self, from: jsonData)
})

You only need to replace "/" to ":". You don't need to do the reverse. The system will take care of the rest.

References