How do you access command line arguments in Swift?
MacosCommand Line-ArgumentsSwiftMacos Problem Overview
How do you access command line arguments for a command line application in Swift?
Macos Solutions
Solution 1 - Macos
Update 01/17/17: Updated the example for Swift 3. Process
has been renamed to CommandLine
.
Update 09/30/2015: Updated the example to work in Swift 2.
It's actually possible to do this without Foundation or C_ARGV
and C_ARGC
.
The Swift standard library contains a struct CommandLine
which has a collection of String
s called arguments
. So you could switch on arguments like this:
for argument in CommandLine.arguments {
switch argument {
case "arg1":
print("first argument")
case "arg2":
print("second argument")
default:
print("an argument")
}
}
Solution 2 - Macos
Solution 3 - Macos
Use the top level constants C_ARGC
and C_ARGV
.
for i in 1..C_ARGC {
let index = Int(i);
let arg = String.fromCString(C_ARGV[index])
switch arg {
case "this":
println("this yo");
case "that":
println("that yo")
default:
println("dunno bro")
}
}
Note that I'm using the range of 1..C_ARGC
because the first element of the C_ARGV
"array" is the application's path.
The C_ARGV
variable is not actually an array but is sub-scriptable like an array.
Solution 4 - Macos
Anyone who wants to use the old "getopt" (which is available in Swift) can use this as reference. I made a Swift port of the GNU example in C one can find at:
http://www.gnu.org/software/libc/manual/html_node/Example-of-Getopt.html
with a full description. It's tested and fully functional. It doesn't require Foundation either.
var aFlag = 0
var bFlag = 0
var cValue = String()
let pattern = "abc:"
var buffer = Array(pattern.utf8).map { Int8($0) }
while true {
let option = Int(getopt(C_ARGC, C_ARGV, buffer))
if option == -1 {
break
}
switch "\(UnicodeScalar(option))"
{
case "a":
aFlag = 1
println("Option -a")
case "b":
bFlag = 1
println("Option -b")
case "c":
cValue = String.fromCString(optarg)!
println("Option -c \(cValue)")
case "?":
let charOption = "\(UnicodeScalar(Int(optopt)))"
if charOption == "c" {
println("Option '\(charOption)' requires an argument.")
} else {
println("Unknown option '\(charOption)'.")
}
exit(1)
default:
abort()
}
}
println("aflag ='\(aFlag)', bflag = '\(bFlag)' cvalue = '\(cValue)'")
for index in optind..<C_ARGC {
println("Non-option argument '\(String.fromCString(C_ARGV[Int(index)])!)'")
}
Solution 5 - Macos
Apple has released the ArgumentParser
library for doing just this:
> We’re delighted to announce ArgumentParser
, a new open-source library that makes it straightforward — even enjoyable! — to parse command-line arguments in Swift.
>
> https://swift.org/blog/argument-parser/
Swift Argument Parser
https://github.com/apple/swift-argument-parser
> Begin by declaring a type that defines the information you need to collect from the command line. Decorate each stored property with one of ArgumentParser
's property wrappers, and declare conformance to ParsableCommand
.
>
> The ArgumentParser
library parses the command-line arguments, instantiates your command type, and then either executes your custom run()
method or exits with useful a message.
Solution 6 - Macos
You could create an argument parser by using the CommandLine.arguments
Array and add any logic you like.
You can test it. Create a file arguments.swift
//Remember the first argument is the name of the executable
print("you passed \(CommandLine.arguments.count - 1) argument(s)")
print("And they are")
for argument in CommandLine.arguments {
print(argument)
}
compile it and run it:
$ swiftc arguments.swift
$ ./arguments argument1 argument2 argument3
The issue with you building your own argument parser is taking into account all the command-line argument conventions. I would recommend using an existing Argument Parser.
You could use:
- Vapor's Console module
- TSCUtility Argument Parser used by the Swift Package manager
- The Swift Argument Parser open-sourced by Apple
I've written about how to build command-line tools on all three. You should check them out and decide what style suits you best.
If you are interested here are the links: