File Paths in Swift

Here’s the translation of the Go code to Swift, with explanations in Markdown format suitable for Hugo:

The Foundation framework provides functions to parse and construct file paths in a way that is portable between operating systems; dir/file on Linux vs. dir\file on Windows, for example.

import Foundation

// Join should be used to construct paths in a portable way.
// It takes any number of arguments and constructs a hierarchical path from them.
let p = NSString.path(withComponents: ["dir1", "dir2", "filename"])
print("p:", p)

// You should always use path(withComponents:) instead of
// concatenating / or \ manually. In addition to providing portability,
// it will also normalize paths by removing superfluous separators
// and directory changes.
print(NSString.path(withComponents: ["dir1//", "filename"]))
print(NSString.path(withComponents: ["dir1/../dir1", "filename"]))

// NSString methods can be used to split a path to the
// directory and the file. 
print("Dir(p):", (p as NSString).deletingLastPathComponent)
print("Base(p):", (p as NSString).lastPathComponent)

// We can check whether a path is absolute.
print((("dir/file" as NSString).isAbsolutePath))
print((("/dir/file" as NSString).isAbsolutePath))

let filename = "config.json"

// Some file names have extensions following a dot. We
// can split the extension out of such names with pathExtension.
let ext = (filename as NSString).pathExtension
print(ext)

// To find the file's name with the extension removed,
// use deletingPathExtension.
print((filename as NSString).deletingPathExtension)

// We can find a relative path between a base and a target.
// It returns nil if the target cannot be made relative to base.
if let rel = NSString(string: "a/b/t/file").relativePath(from: "a/b") {
    print(rel)
}

if let rel = NSString(string: "a/c/t/file").relativePath(from: "a/b") {
    print(rel)
} else {
    print("Cannot make path relative")
}

To run the program, save it as FilePaths.swift and use swift command:

$ swift FilePaths.swift
p: dir1/dir2/filename
dir1/filename
dir1/filename
Dir(p): dir1/dir2
Base(p): filename
false
true
json
config
t/file
Cannot make path relative

Note that Swift’s file path handling is somewhat different from Go’s. We’re using NSString methods here because they provide similar functionality to Go’s filepath package. The Foundation framework in Swift doesn’t have a direct equivalent to Go’s filepath.Rel, so we’ve used relativePath(from:) which is similar but returns nil instead of an error when the path can’t be made relative.