37

I am redesigning a command line application and am looking for a way to make its use more intuitive. Are there any conventions for the format of parameters passed into a command line application? Or any other method that people have found useful?

Jeff Atwood
  • 63,320
  • 48
  • 150
  • 153
lillq
  • 14,758
  • 20
  • 53
  • 58

17 Answers17

29

I see a lot of Windows command line specifics, but if your program is intended for Linux, I find the GNU command line standard to be the most intuitive. Basically, it uses double hyphens for the long form of a command (e.g., --help) and a single hyphen for the short version (e.g., -h). You can also "stack" the short versions together (e.g., tar -zxvf filename) and mix 'n match long and short to your heart's content.

The GNU site also lists standard option names.

The getopt library greatly simplifies parsing these commands. If C's not your bag, Python has a similar library, as does Perl.

yukondude
  • 24,013
  • 13
  • 49
  • 58
  • 4
    For Windows, the de facto standard is using `/foo` (but also support `-foo`, BSD-style) for parameterless switches, and `/foo:value` (again, with alternative `-foo:falue`) for those with parameters. In other words, the syntax used by all Microsoft command line tools (Win32 out of the box, development tools, and so on). – Pavel Minaev Jul 26 '09 at 08:45
  • In Python, use optparse - http://docs.python.org/library/optparse.html - it's *so much* nicer to use than getopt – dbr Jul 26 '09 at 09:50
  • 1
    @dbr, optparse is deprecated now though, in favour of http://docs.python.org/library/argparse.html – Teo Klestrup Röijezon Jan 01 '12 at 03:02
  • the term "bundling" is perhaps more common to describe the practice of grouping short options together than "stacking" – Todd Freed Jan 23 '14 at 22:03
14

If you are using C# try Mono.GetOptions, it's a very powerful and simple-to-use command-line argument parser. It works in Mono environments and with Microsoft .NET Framework.

EDIT: Here are a few features

  • Each param has 2 CLI representations (1 character and string, e.g. -a or --add)
  • Default values
  • Strongly typed
  • Automagically produces an help screen with instructions
  • Automagically produces a version and copyright screen
Alfred Myers
  • 6,384
  • 1
  • 40
  • 68
Sklivvz
  • 30,601
  • 24
  • 116
  • 172
  • 4
    Looks like Mono is obsoleting theirs and referring to NDesk.Options: http://ndesk.org/Options – quip Dec 07 '09 at 21:50
4

One thing I like about certain CLI is the usage of shortcuts.
I.e, all the following lines are doing the same thing

myCli.exe describe someThing
myCli.exe descr someThing
myCli.exe desc someThing

That way, the user may not have to type the all command every time.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • This method is especially useful with tools like Darcs, Git, and Subversion, where there is essentially a suite of related but distinct commands. – Josh Lee Oct 10 '08 at 14:03
  • Exactly! Except I use that feature for another version control CLI: cleartool (ct) of ClearCase ;). Since I also manage Subversion repositories, I do my fair share of svn and svnadmin commands... – VonC Oct 10 '08 at 14:40
4

A good and helpful reference:

https://commandline.codeplex.com/

Library available via NuGet:

  1. Latest stable: Install-Package CommandLineParser.
  2. Latest release: Install-Package CommandLineParser -pre.

One line parsing using default singleton: CommandLine.Parser.Default.ParseArguments(...).
One line help screen generator: HelpText.AutoBuild(...).
Map command line arguments to IList<string>, arrays, enum or standard scalar types.
Plug-In friendly architecture as explained here.
Define verb commands as git commit -a.
Create parser instance using lambda expressions.

QuickStart: https://commandline.codeplex.com/wikipage?title=Quickstart&referringTitle=Documentation

// Define a class to receive parsed values
class Options {
  [Option('r', "read", Required = true,
    HelpText = "Input file to be processed.")]
  public string InputFile { get; set; }

  [Option('v', "verbose", DefaultValue = true,
    HelpText = "Prints all messages to standard output.")]
  public bool Verbose { get; set; }

  [ParserState]
  public IParserState LastParserState { get; set; }

  [HelpOption]
  public string GetUsage() {
    return HelpText.AutoBuild(this,
      (HelpText current) => HelpText.DefaultParsingErrorsHandler(this, current));
  }
}

// Consume them
static void Main(string[] args) {
  var options = new Options();
  if (CommandLine.Parser.Default.ParseArguments(args, options)) {
    // Values are available here
    if (options.Verbose) Console.WriteLine("Filename: {0}", options.InputFile);
  }
}
Kiquenet
  • 14,494
  • 35
  • 148
  • 243
3

Best thing to do is don't assume anything if you can. When the operator types in your application name for execution and does not have any parameters either hit them with a USAGE block or in the alternative open a Windows Form and allow them to enter everything you need.

c:\>FOO

FOO

USAGE FOO -{Option}{Value}

-A Do A stuff
-B Do B stuff

c:\>

Parameter delimiting I place under the heading of a religious topic: hyphens(dashes), double hyphens, slashes, nothing, positional, etc.

You didn't indicate your platform, but for the next comment I will assume Windows and .net

You can create a console based application in .net and allow it to interact with the Desktop using Forms just by choosing the console based project then adding the Windows.Forms, System.Drawing, etc DLLs.

We do this all the time. This assures that no one takes a turn down a dark alley.

Bill
  • 1,738
  • 10
  • 22
3

Here's a CodeProject article that might help you out...

C#/.NET Command Line Arguments Parser

IF VB is your flavor, here's a separate article (with a bit more guidance related content) to check out...

Parse and Validate Command Line Parameters with VB.NET

Sean Gough
  • 1,721
  • 3
  • 26
  • 47
3

Command line conventions vary from OS to OS, but the convention that's probably gotten both the most use, and the most public scrutiny is the one supported by the GNU getopt package. See http://www.gnu.org/software/libc/manual/html_node/Using-Getopt.html for more info.

It allows you to mix single letter commands, such as -nr, with longer, self-documenting options, such as --numeric --reverse. Be nice, and implement a --help (-?) option and then your users will be able to figure out all they need to know.

Kimbo
  • 153
  • 2
  • 4
  • 6
3

Complementing @vonc's answer, don't accept ambiguous abbreviations. Eg:

  myCli.exe describe someThing
  myCli.exe destroy someThing
  myCli.exe des someThing ???

In fact, in that case, I probably wouldn't accept an abbreviation for "destroy"...

Brent.Longborough
  • 9,567
  • 10
  • 42
  • 62
  • 2
    Good point, disambiguation is another criteria to take into account... +1 to you, Sir. – VonC Sep 24 '08 at 19:16
2

I always add a /? parameter to get help and I always try to have a default (i.e. most common scenario) implementation.

Otherwise I tend to use the "/x" for switches and "/x:value" for switches that require values to be passed. Makes it pretty easy to parse the parameters using regular expressions.

Sean Gough
  • 1,721
  • 3
  • 26
  • 47
1

I developed this framework, maybe it helps:

The SysCommand is a powerful cross-platform framework, to develop Console Applications in .NET. Is simple, type-safe, and with great influences of the MVC pattern.

https://github.com/juniorgasparotto/SysCommand

namespace Example.Initialization.Simple
{
    using SysCommand.ConsoleApp;

    public class Program
    {
        public static int Main(string[] args)
        {
            return App.RunApplication();
        }
    }

    // Classes inheriting from `Command` will be automatically found by the system
    // and its public properties and methods will be available for use.
    public class MyCommand : Command
    {
        public void Main(string arg1, int? arg2 = null)
        {
            if (arg1 != null)
                this.App.Console.Write(string.Format("Main arg1='{0}'", arg1));
            if (arg2 != null)
                this.App.Console.Write(string.Format("Main arg2='{0}'", arg2));
        }

        public void MyAction(bool a)
        {
            this.App.Console.Write(string.Format("MyAction a='{0}'", a));
        }
    }
}

Tests:

// auto-generate help
$ my-app.exe help

// method "Main" typed
$ my-app.exe --arg1 value --arg2 1000

// or without "--arg2"
$ my-app.exe --arg1 value

// actions support
$ my-app.exe my-action -a
Junior
  • 199
  • 1
  • 9
0

-operation [parameters] -command [your command] -anotherthings [otherparams]....

For example,

YourApp.exe -file %YourProject.prj% -Secure true
Graviton
  • 81,782
  • 146
  • 424
  • 602
0

If you use one of the standard tools for generating command line interfaces, like getopts, then you'll conform automatically.

jodonnell
  • 49,859
  • 10
  • 62
  • 67
0

The conventions that you use for you application would depend on

1) What type of application it is.
2) What operating system you are using. Linux? Windows? They both have different conventions.

What I would suggest is look at other command line interfaces for other commands on your system, paying special attention to the parameters passed. Having incorrect parameters should give the user solution directed error message. An easy to find help screen can aid in usability as well.

Without know what exactly your application will do, it's hard to give specific examples.

Alan H
  • 3,021
  • 4
  • 25
  • 24
  • Why does it matter whether I am writing for Linux vs Windows? I think that there should be a standard format that is universal between the two. If you have more insight on this and are willing to share, let me know. – lillq Sep 20 '08 at 17:47
  • It matters because the two operating systems do things differently. In the example of parameters to command line applications, linux uses - and windows uses / for specifying switches. ls -l in unix, dir /ah for windows. To pick one difference. –  Oct 13 '11 at 08:56
  • @lillq maybe there should be a shared format between the two but there isn't. – jwg Mar 22 '13 at 14:00
0

The conventions that you use for you application would depend on

1) What type of application it is. 2) What operating system you are using.

This is definitely true. I'm not certain about dos-prompt conventions, but on unix-like systems the general conventions are roughly:

1) Formatting is

appName parameters

2) Single character parameters (such as 'x') are passed as -x 3) Multi character parameters (such as 'add-keys') are passed as --add-keys

donair
  • 21
  • 2
0

If you're using Perl, my CLI::Application framework might be just what you need. It lets you build applications with a SVN/CVS/GIT like user interface easily ("your-command -o --long-opt some-action-to-execute some parameters").

jkramer
  • 15,440
  • 5
  • 47
  • 48
0

I've created a .Net C# library that includes a command-line parser. You just need to create a class that inherits from the CmdLineObject class, call Initialize, and it will automatically populate the properties. It can handle conversions to different types (uses an advanced conversion library also included in the project), arrays, command-line aliases, click-once arguments, etc. It even automatically creates command-line help (/?).

If you are interested, the URL to the project is http://bizark.codeplex.com. It is currently only available as source code.

Brian
  • 37,399
  • 24
  • 94
  • 109
0

I've just released an even better command line parser.
https://github.com/gene-l-thomas/coptions
It's on nuget Install-Package coptions

using System;
using System.Collections.Generic;
using coptions;

[ApplicationInfo(Help = "This program does something useful.")]
public class Options
{
    [Flag('s', "silent", Help = "Produce no output.")]
    public bool Silent;

    [Option('n', "name", "NAME", Help = "Name of user.")]
    public string Name
    {
        get { return _name;  }
        set { if (String.IsNullOrWhiteSpace(value))
                throw new InvalidOptionValueException("Name must not be blank");
              _name = value;
        }
    }
    private string _name;

    [Option("size", Help = "Size to output.")]
    public int Size = 3;

    [Option('i', "ignore", "FILENAME", Help = "Files to ignore.")]
    public List<string> Ignore;

    [Flag('v', "verbose", Help = "Increase the amount of output.")]
    public int Verbose = 1;

    [Value("OUT", Help = "Output file.")]
    public string OutputFile;

    [Value("INPUT", Help = "Input files.")]
    public List<string> InputFiles;
}

namespace coptions.ReadmeExample
{
    class Program
    {
        static int Main(string[] args)
        {
            try
            {
                Options opt = CliParser.Parse<Options>(args);

                Console.WriteLine(opt.Silent);
                Console.WriteLine(opt.OutputFile);
                return 0;
            }
            catch (CliParserExit)
            {
                // --help
                return 0;

            } catch (Exception e)
            {
                // unknown options etc...
                Console.Error.WriteLine("Fatal Error: " + e.Message);
                return 1;
            }
        }
    }
}

Supports automatic --help generation, verbs, e.g. commmand.exe
Enjoy.

Gene
  • 21
  • 3
  • Your link is broken. So there is no accompanied documentation. BTW, your lib seems to be a clone of [gsscoder command line parser](https://github.com/gsscoder/commandline)... – AlexMelw Jan 15 '18 at 18:08
  • 1
    I looked at [command line](https://github.com/commandlineparser/commandline) and [clipr](https://github.com/nemec/clipr) before I looked at coding anything as both use annotations. I have hugely extended clipr whose code was of better quality, and the API was tidier, but ended up using the sensible named [Option] and [Value], adding [Flag] which is different to the user (no value). I have now added support for populating fields (less typing), /windows and -x11 style options. And parsing .ini files. The link will be https://github.com/GeneThomas/coptions . – Gene Jan 22 '18 at 19:54