Anthony Mittaz
Anthony Mittaz

Reputation: 1601

How do you access command line arguments in Swift?

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

Upvotes: 152

Views: 63640

Answers (6)

rderik
rderik

Reputation: 510

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:

Upvotes: 11

pkamb
pkamb

Reputation: 34993

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.

Upvotes: 16

Mark Adams
Mark Adams

Reputation: 30846

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")
    }
}

Upvotes: 329

orj
orj

Reputation: 13484

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.

Upvotes: 45

Maciek Czarnik
Maciek Czarnik

Reputation: 6181

In Swift 3 use CommandLine enum instead of Process

So:

let arguments = CommandLine.arguments

Upvotes: 68

Michele Dall'Agata
Michele Dall'Agata

Reputation: 1504

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)])!)'")
}

Upvotes: 14

Related Questions