Command-line arguments: Part 2
Tags: python, productivity, opensource, management
Published: 2019-11-11 19:12:22

And...We're back, once more with our CLI programming. We're taking a deeper dive into the waters of command-line arguments, this time, looking at a friend to `argv` ;  *using* `argparse`. That's right, it's a whole family.

Last time we talked, we had a whole array of possibilities with using `argv`, but what if I told you there is much more that could be done while using its big brother module? Let's see what this just means.

Before, we used `argv` to get the square of a number, passing in the number we wanted the square of and getting the result. What if we had a new user who did not know how to work with the program and you weren't there to explain your new-found love for CLI programs? What if you wanted your program to do more than just print the result right to your face? Okay, I had to laugh a little on that last bit. Let's give it a shot on how we would get this to work seamlessly.

```
# advanced_square.py
# get the square of numbers using command_line_arguments

import argparse

parser = argparse.ArgumentParser(description="get the square of the input value")

parser.add_argument("square", type=int)

arguments = parser.parse_args()

print(arguments.square**2)

```

If you haven't noticed yet, we have used the very same example we used in the last section only this time, we called in some help. Time to open the cookie jar.
```
parser = argparse.ArgumentParser(description="get the square of the input value")
```
Above, we are simply giving the program description. (* What does this program do? *). 
Unlike the previous section where we just parse in arguments and use a list to get the item we want, here, we specify using the below line:

```
parser.add_argument("square", type=int)
```

Above, apart from giving the program description, we have *added an argument* which is an object of type `int`, a number. We state beforehand and tell the program to expect this type of integer. We tell the program to *name this variable* `square` so that we can retrieve it with that same variable name.

Take a look at this line:
```
arguments = parser.parse_args()
```
All our arguments added are contained in our variable called `parser`. Using `parse_args ` is a way of getting our variables from the whole lot we might have added and within it, we have a tuple like object:
```
Namespace(square=8)
# note that the number after the equal sign depends on what you have #passed to the program as an argument
```
Adding more arguments would increase its size with the respective mapping of value to variable name. For simplicity sake, we place all this into a variable called `arguments` which will hold whatever arguments we may have passed to the program after which, we call the variable we want to work with its name using `arguments.square` and do the math printing it to the terminal. Hence,
```
python advanced_square.py 8
64
 ```
Note how using `argparse ` gives us a little push help. For instance, with the current file, if we use the common `-h` or `--help` for assistance when we amnesia, we get something like this:
```
python advanced_square.py --help
usage: advanced_square.py [-h] square 

get the square of the input value

positional arguments:
  square      the input value whose square is needed
 
optional arguments:
  -h, --help  show this help message and exit

```
Our program description is nicely printed to anyone who would want to know about what we do within the program while our arguments are printed with their details.
We pass in the number we want to square because we simply cannot square an empty space! Wait, can we?


Now as much as we would love to, we cannot keep subtracting numbers all day! Just to show you how powerfull `argparse ` can be, we are going to modify one of the programs we did in [the second piece](https://marvin.hashnode.dev/file-management-with-python-ck02cpxu30010fqs1stv451gx) of [File management with python](https://marvin.hashnode.dev/file-management-with-python-ck02cpxu30010fqs1stv451gx). Do go through that, if you haven't already, and get back once done. 

We modify the program as below:
```
import os
import shutil
import glob
import argparse


def organize(folder):
    """Organize files according to extension """

    # get into the directory passed
    os.chdir(folder)
    all_files = [x for x in os.listdir('.')]

    file_types = set((os.path.splitext(f)[1] for f in all_files))

    for ftype in file_types:
        new_directory = ftype.replace(".", '')
        os.mkdir(new_directory)

        for fname in glob.glob(f'*.{ftype[1:]}'):
            shutil.move(fname, new_directory)



def main():
    parser = argparse.ArgumentParser(description="sort files according to file extension")

    parser.add_argument("path", help="Path of directory with unsortsed files")
    parser.add_argument("-v","--verbose", help="Descriptive message of directory after sort", action="store_true")


    arguments = parser.parse_args()

    organize(arguments.path)

    if arguments.verbose:
        print("\n The following files were extensions were found and organized successfully...")
        print(os.listdir('.'))
    else:
        print("Done!")
    

main()

```

Now that is much better! Things are finally starting to take shape. You have the option to either:

1. Pass the relative/absolute path of the *messy* directory to clean
                                                      
2. Pass the path to the directory with an optional argument `-v` or `--verbose` to list the folders in the *cleaned up* directory.

We intend to advance on our knowledge on command-line arguments in next week's article, but for now, take a break, relax and let it sink in. 

You can go through the code section, at [TheGreenCodes](https://github.com/TheGreenCodes/CommandLineArguments) and or give out your thoughts or ideas on just what you think is possible with what we have done so far! 

Cheers!