Command Line Swift
#!/usr/bin/awesome
This post is mostly a brain dump of what it takes to use Swift for command line scripting.
Update: I've added -S
to env
. This makes things compatible with recent versions of FreeBSD. There doesn't appear to be a portable solution for Linux because it treats the entire line after the first space as a single argument rather than splitting into multiple arguments and its version of env
doesn't support -S
.
#!/usr/bin/env -S xcrun --toolchain <X> swift
import Foundation
The first step is to decide which version of Swift you want to use. Replace <X>
with the toolchain identifier from Xcode.app/Contents/Developer/Toolchains/<X>/ToolchainInfo.plist
.
com.apple.dt.toolchain.Swift_2_3
- this is the toolchain you get if you don't specify a toolchain or use/usr/bin/swift
directly (when executing Swift scripts on macOS Sierra or earlier)com.apple.dt.toolchain.XcodeDefault
- this is the toolchain you get if you specify an invalid toolchain identifier.
If in doubt, consult this handy table:
toolchain | swift version |
---|---|
com.apple.dt.toolchain.XcodeDefault | Swift 3.x |
com.apple.dt.toolchain.Swift_2_2 (invalid) | Swift 3.x |
Cookies! (invalid) | Swift 3.x |
com.apple.dt.toolchain.Swift_2_3 | Swift 2.3 |
(unspecified) | System Swift |
I wish you could specify the specific Swift version you wanted instead (rdar://problem/28409078)
Options
You can also pass options to Swift this way:
#!/usr/bin/env -S xcrun --toolchain <X> swift -F/my/frameworks -framework MyUtils.framework -D FLAG
This works just like invoking the compiler or REPL. -F
adds a framework search path. -framework
adds a framework to load. -D
adds a conditional compilation flag.
If you have a collection of personal utilities you'd like to use from scripts just build a framework, drop it somewhere like /usr/local/lib
, and specify the path and framework name in your script.
If you'd prefer something more automated, check out cato which handles picking a Swift version, uses Cocoapods to download frameworks, builds them, and invokes your script with Swift.
Args and Misc
In Swift 3 use CommandLine.arguments
. Index zero is the command itself (in this case your script).
Remember you still need to import <framework>
, including Foundation
.
Use Process
to launch other commands. You can hook its standard input/output up to a Pipe
if you want to capture the output.
Conclusion
Are you writing scripts in Swift? Have any tips or tricks? Please leave a comment!
This blog represents my own personal opinion and is not endorsed by my employer.