Last active
April 26, 2025 13:09
-
-
Save erica/9f5186d6ae90d479de4d81dc2e6d60b2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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