1

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.

closed as off-topic by muru, Jacob Vlijm, Eric Carvalho, user.dz, MadMike Jun 9 '16 at 5:22

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "This is not about Ubuntu. Questions about other Linux distributions can be asked on Unix & Linux, those about Windows on Super User, those about Apple products on Ask Different and generic programming questions on Stack Overflow." – muru, user.dz, MadMike
If this question can be reworded to fit the rules in the help center, please edit the question.

  • Would you prefer a python answer? – Jacob Vlijm Jun 1 '16 at 11:13
  • @JacobVlijm : yes please .. I am open to any solution – McLan Jun 1 '16 at 11:23
  • "I want to be able to create a command with a configuration file. So that the user enter the answers for the questions above as options in the command line itself." I don't see how these two requirements line up. Do you want defaults to specified in a config file, and optionally overriden by command-line arguments? In any case, this is just generic programming and should be asked on Stack Overflow. – muru Jun 1 '16 at 12:08
  • You are right, it is a little bit confusing. I want to have the default values specified in the config file, and overridden (or give more precision to the output) by command line argument. Regards the question: I thought it is related to Ubuntu, my apologies. @muru – McLan Jun 1 '16 at 15:26
  • 1
    @Suda.nese thanks, I'd appreciate that. (of course) no appoligies needed (at all) on the language. There are people from numerous origins posting here, that's part of the fun. We need however to create a question and answer combination that fit together. An open end; a question that remains unclear with a set of answers that miss target, that's not in your interest as well. If I can help with that anyhow, please mention. – Jacob Vlijm Jun 2 '16 at 9:49
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
    
  • 1
    Consider using getopt or argparse instead of writing your own argument parser – muru Jun 1 '16 at 12:16
  • @muru, AHA, nice, have to teach this afternoon, but will look into it. Thanks! – Jacob Vlijm Jun 1 '16 at 12:17
  • It is almost what I need, yet not exactly. Thank you anyway for the answer. I want to write a command script that runs the python code. The user fill the command arguments before it is executed (just like running "ls" command where arguments are in "-l" or "-a" format. While the command is running, the user arguments are passed to the python code which override the default values for these arguments in case they have values, otherwise use the default values. I just want to create look-alike linux commands with options and arguments. @jacobvlijm – McLan Jun 1 '16 at 15:38
  • @Suda.nese that is exactly what the answer is doing. please clarify. – Jacob Vlijm Jun 2 '16 at 5:21
  • @Suda.nese updated my answer. Please see if this is what you are looking for. – Jacob Vlijm Jun 2 '16 at 18:15
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
  • Thanks for the answer. I already have similar setup. but I need to give the user the possibility to change how to run the command by writing arguments associated to the command "pcap". Just like running any linux command with --help or --<anything else> arguments – McLan Jun 1 '16 at 15:42
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.

Not the answer you're looking for? Browse other questions tagged or ask your own question.