Skip to content

Instantly share code, notes, and snippets.

@erica
Last active April 26, 2025 13:09
Show Gist options
  • Save erica/9f5186d6ae90d479de4d81dc2e6d60b2 to your computer and use it in GitHub Desktop.
Save erica/9f5186d6ae90d479de4d81dc2e6d60b2 to your computer and use it in GitHub Desktop.
#!/usr/bin/xcrun swift
import Cocoa
let manager = FileManager.default
// NSString workarounds
extension String {
var lastPathComponent: String {
return (self as NSString).lastPathComponent
}
func appendingPathComponent(_ string: String) -> String {
return (self as NSString).appendingPathComponent(string)
}
}
// Fetch arguments and test for usage
var arguments = CommandLine.arguments
let appName = arguments.remove(at: 0).lastPathComponent
func usage() -> Never { print("Usage: \(appName) location1 location2"); exit(-1) }
guard arguments.count == 2 else { usage() }
// Success and Fail outcomes
func success(_ url: URL) -> Never { print("Created symbolic link at \(url.path)"); exit(0) }
func fail(_ reason: String) -> Never { print("Cannot create symbolic link: ", reason); exit(-1) }
// Perform link
func link(_ target: URL, to source: URL) throws {
if manager.fileExists(atPath: target.path) {
fail("File already exists at destination '\(target.path)'")
}
try manager.createSymbolicLink(at: target, withDestinationURL: source)
success(target)
}
// Establish preliminary URLs
var url1 = URL(fileURLWithPath: arguments[0])
var url2 = URL(fileURLWithPath: arguments[1])
guard url1 != url2 else { fail("Cannot link an item to itself") }
// Precalculate configurations
var (isDir1, isDir2): (ObjCBool, ObjCBool) = (false, false)
let exists1 = manager.fileExists(atPath: url1.path, isDirectory: &isDir1)
let exists2 = manager.fileExists(atPath: url2.path, isDirectory: &isDir2)
let url1with2 = URL(fileURLWithPath: url1.path.appendingPathComponent(url2.lastPathComponent))
let url2with1 = URL(fileURLWithPath: url2.path.appendingPathComponent(url1.lastPathComponent))
do {
var destURL: URL
switch (isDir1.boolValue, isDir2.boolValue) {
case (false, true): // file1, dir2
switch(exists1, exists2) {
case (false, true): try link(url1, to: url2)
case (true, true): try link(url2with1, to: url1)
case (true, false): fail("Can't link file to nonexistent folder")
case (false, false): fail("Neither item currently exists")
}
case (true, false): // file2, dir1
switch(exists2, exists1) {
case (false, true): try link(url2, to: url1)
case (true, true): try link(url1with2, to: url2)
case (true, false): fail("Can't link file to nonexistent folder")
case (false, false): fail("Neither item currently exists")
}
case (false, false): // both files
switch (exists1, exists2) {
case (true, true): fail("Both files already exist")
case (false, false): fail("Neither file currently exists")
default:
let (targetURL, sourceURL) = exists1 ? (url2, url1) : (url1, url2)
try link(targetURL, to: sourceURL)
}
case (true, true): // both directories
switch (arguments[0] == ".", arguments[1] == ".") {
case (false, false): fail("Can't decide which directory to symbolic link to the other")
case (true, _): try link(url1with2, to: url2)
case (_, true): try link(url2with1, to: url1)
default: break
}
}
} catch {
print(error)
exit(-1)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment