2

Directly to the point, I want to give the user the flexibility to pass arguments to a command in order to control how the commands should run, something like:

pcap -d 30 -w 2

In other words:

I want to make a command that looks exactly like Linux commands. A command that works exactly as Linux commands. A command that has options (i.e.: arguments) in the same style as Linux commands.

I want to create a command that works by taking arguments from the user or by using its default arguments (read from a configuration file) in case no arguments are supplied by the user, exactly like any other Linux commands.

A command with --help that shows the different options.

I know how to make a command in Linux. But I don't know how to make these options (command arguments). I don't know how these arguments are programmed.

a guide, a tutorial or an example will do

Note:

  1. Apologies if this question is asked in the wrong stack.
  2. Also apologies for the previous version of the question, it was badly phrased.
Jacob Vlijm
  • 85,475
McLan
  • 251

3 Answers3

3

Since you mention python, a python answer:

if you simply want to set a default value for an argument, you can simply set the default for the function:

def show(val = 30):
    print(val)
# to print the default value (30)
show()
# to show another value (e.g. 40)
show(40)

In other words, this will print the default value if you give no argument, while it uses the argument if you give it.

More advanced; reading the default values from a file, with the option to overrule by giving the arguments

The very same can be done, but reading default arguments from a file. This will give the opportunity to set arguments in a settings file instead of editing them in the code itself.

Let's say I have a settings file, testconf.txt:

length:4
height:7
width:6

...and I want to read these values into my application as default arguments, but the user can overrule them by custom arguments:

#!/usr/bin/env python3
import sys

# path to my config file
conf_file = "/home/jacob/Bureaublad/testconf.txt"
# read the default arguments from a file
def_args = [l.strip() for l in open(conf_file).readlines()]
# replace default args by possible custom args
cust_args = sys.argv[1:]
for cu in cust_args:
    argname = cu.split(":")[0]
    try:
        match = [arg for arg in def_args if arg.startswith(argname)][0]
    except IndexError:
        print("incorrect argument: ", cu)
    else:
        def_args[def_args.index(match)] = cu

def get_arg(s):
    return [val.split(":")[1] for val in def_args if val.startswith(s)][0]

l = get_arg("length")
w = get_arg("width")
h = get_arg("height")

print("l=", l, "w=", w, "h=", h)

Now I can run the script without arguments:

$ '/home/jacob/Bureaublad/pscript_4.py'
l= 4 w= 6 h= 7

Or width arguments:

$ '/home/jacob/Bureaublad/pscript_4.py' length:10 height:456
l= 10 w= 6 h= 456

The order of given arguments is in this setup irrelevant. In case of an incorrect argument:

$ '/home/jacob/Bureaublad/pscript_4.py' monkey
incorrect argument:  monkey
l= 4 w= 6 h= 7

Note

In "real" software, you can (and should) make it more advanced of course by adding a warning if the settings file is incorrect or missing, decide what to do then, but this is the basic idea.


EDIT

From your comments, I understand that in two ways, the above answer is not (yet) what you are looking for:

  1. You'd like to run the command without the path to the executable (script), and its extension, and
  2. You'd like to have a more "conventional" format of the options.

Although [1] is anwered elsewhere already, I'll include a brief explanation here:

1. Run the command without path and extension

You can run executables and scripts without having to include the path to the script by making it executable (chmod +x <files>), and place them anywhere in $PATH.

On Linux, the extension (.py) does not play a role whatsoever, so you can use the script without extension anyway.

To be concrete:

  • create, if it doesn't exist yet, the directory ~/bin
  • create and save the script, exactly as mentioned in the original answer, as showsize (no extenion) in ~/bin, and make the script executable.

    After a log out/in, you can simply run the script by the command:

    showsize
    

2. Change the format of the options

As mentioned, you can change the format of the options easily, e.g.: To parse out the options, given like:

-l 23 -h 210 -w 321
  • If you include in the script:

    args = sys.argv[1:]

    The result for argswill be a list:

    ["-l", "23", "-h", "210", "-w", "321"]
    

    Now what we need to do to get the value of -h, is simply look up the index of -h, and pick the first next item in the list:

    height = args[args.index("-h")+1]
    print(height)
    
    > 210
    

    in a script:

    #!/usr/bin/env python3
    import sys
    
    # path to my config file
    conf_file = "/home/jacob/Bureaublad/testconf.txt"
    # read the default arguments from a file
    def_args = [l.strip().split(":") for l in open(conf_file).readlines()]
    # replace default args by possible custom args
    cust_args = sys.argv[1:]
    for carg in cust_args:
        if carg in ["-l", "-h", "-w"]:                        
            for d in def_args:
                d[1] = cust_args[cust_args.index(carg)+1] if d[0] == carg else d[1]
    
    def get_arg(s):
        # fetch values from the list
        return [val[1] for val in def_args if val[0] == s][0]
    
    l = get_arg("-l")
    w = get_arg("-w")
    h = get_arg("-h")
    
    print("length =", l, "\nwidth =", w, "\nheight =", h)
    

How to use

  1. Create your settings file in the format:

    -l:4
    -h:7
    -w:6
    
  2. Copy the script into an empty file, svae it as showsize (no extension) in ~/bin or anywhere else in $PATH, and make it executable.

  3. In the head section of the script, set the path to the settings file:

    # path to my config file
    conf_file = "/home/jacob/Bureaublad/testconf.txt"
    

    Now run the command:

    $ showsize
    length = 4 
    width = 6 
    height = 7
    

    Or:

    $ showsize -l 300 -h 345 -w 751
    length = 300 
    width = 751 
    height = 345
    
Jacob Vlijm
  • 85,475
2

Script file:

#!/bin/bash

# set default values
X=10
Y="lorem ipsum"

source ~/.myscript.conf

echo "X = $X, Y = $Y"

.myscript.conf file:

X=20
Y="something else"

Now, if a user runs script file and does not have .myscript.conf file in his home directory, script will use X=10 and Y="lorem ipsum", if there is config file, it will use values from the file.

Source command executes contents of the file given as an argument in current shell, so here, it will assign new values to X and Y overwriting defaults from the script file.

Since ~ points to user home directory this setup will work for any user on your system (also root).

[Edit] And in your specific example:

#!/bin/bash
X=10
Y=2
source ~/.config.conf
pcap -d $X -w $Y
1

Bash: same as Marek's with sourcing a file with user's values, with the caveat that this file can do anything, and typos will just elicit syntax errors, so this requires a bit of user know-how. You can parse command line parameters with getopts.

Python: see the argparse module to parse command line parameters, and ConfigParser(v2) and configparser(v3) to parse a .ini file.

Typically you use a config file for things that don't change often, and command line parameters for things that are likely different on each run. Editing a config file on each run is a PITA.

xenoid
  • 5,759