How do you access command line arguments in Swift?

48,370

Solution 1

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 2

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 Strings 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 3

In Swift 3 use CommandLine enum instead of Process

So:

let arguments = CommandLine.arguments

Solution 4

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 5

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)])!)'")
}
Share:
48,370
Anthony Mittaz
Author by

Anthony Mittaz

Xcoder...

Updated on July 08, 2020

Comments

  • Anthony Mittaz
    Anthony Mittaz about 4 years

    How do you access command line arguments for a command line application in Swift?

  • Jack Lawrence
    Jack Lawrence about 10 years
    You can also use NSProcessInfo, just like you do in Objective-C.
  • orj
    orj about 10 years
    NSProcessInfo requires Foundation. My answer doesn't require Foundation. Just uses swift lang standard lib.
  • Albin Stigo
    Albin Stigo over 9 years
    If you want an array this construct is quite handy let args = [String](Process.arguments)
  • Lance
    Lance over 9 years
    @AlbinStigo Process.arguments is already an array of strings, no need to make a new one.
  • HepaKKes
    HepaKKes over 9 years
    As almost always the best answer is not the the accepted one. :)
  • juandesant
    juandesant almost 9 years
    println has been changed to print recently, but indeed this is the best answer.
  • juandesant
    juandesant almost 9 years
    C_ARCG seems to no longer be supported.
  • robobrobro
    robobrobro over 8 years
    If anyone besides me cares, Process is actually an enumeration.
  • svth
    svth over 8 years
    I can confirm that C_ARG no longer works with the latest version of the tools, XCode Version 7.1 (7B91b).
  • Honghao Zhang
    Honghao Zhang about 8 years
    Use of unresolved identifier 'C_ARGC', not supported anymore on Xcode 7.3
  • Franklin Yu
    Franklin Yu about 8 years
    Is Process.arguments the same as NSProcessInfo.processInfo().arguments?
  • Alonso Urbano
    Alonso Urbano almost 8 years
    Operator .. is not defined for ranges, it's either ... or ..<
  • TheSoundDefense
    TheSoundDefense almost 8 years
    In the most recent Swift snapshots (either the 7/28 snapshot or the 7/29 snapshot), the Process object is now known as the CommandLine object. This will probably be fully incorporated once Swift 3.0 is officially released.
  • TheSoundDefense
    TheSoundDefense almost 8 years
    You can instead use Process.argc and Process.arguments for this, though it looks like this might be changing to CommandLine.argc and CommandLine.arguments with the most recent changes to the language.
  • BTRUE
    BTRUE about 7 years
    Look at @marc adams 's answer below, instead of this one.
  • d4Rk
    d4Rk over 6 years
    Swift 4: ProcessInfo().arguments