Tagged: bash

Getopt in Bash

There are two different ways of parsing command line arguments while using getopt(3). There is an utility called getopt (man 1 getopt). This utility is available in all shells. Then in bash, there is another built-in tool for parsing arguments called getopts (it’s a built-in, so it doesn’t have it’s own man-page — try help getopts).

getopt(1)

Here’s an example script that demonstrates the usage of getopt:

#!/bin/bash

# Execute getopt
ARGS=`getopt -o "123:" -l "one,two,three:" \
      -n "getopt.sh" -- "$@"`

#Bad arguments
if [ $? -ne 0 ];
then
  exit 1
fi

# A little magic
eval set -- "$ARGS"

# Now go through all the options
while true;
do
  case "$1" in
    -1|--one)
      echo "Uno"
      shift;;

    -2|--two)
      echo "Dos"
      shift;;

    -3|--three)
      echo "Tres"

      # We need to take the option argument
      if [ -n "$2" ];
      then
        echo "Argument: $2"
      fi
      shift 2;;

    --)
      shift
      break;;
  esac
done

At first, the getopt utility is called with desired parameters (see man getopt for detailed description of all the options). If it returns anything else than 0, something was wrong and we’ll end the script. There is no error message necessary, because the getopt itself will inform user about what went wrong.

After that, there’s a little magic line with eval and set. It’s there to preserve whitespaces inside options arguments. Detailed description of this technique is here.

All options are evaluated and appropriate actions take place in the while loop at the end of the script.

getopts

Here’s an example script that demonstrates the usage of getopts:

#!/bin/bash

while getopts "123:" OPTION
do
  case $OPTION in
    1)  echo "Uno";;
    2)  echo "Dos";;
    3)  echo "Tres: $OPTARG";;

    # Unknown option. No need for an error, getopts informs
    # the user itself.
    \?) exit 1;;
  esac
done

As you can see, the bash built-in version is easier to use, but it can’t handle long options like --option.

Conclusion

Which one you should use? Well, it’s up to you, what you need. If you’re looking for compatibility of your script among more shells than just bash or want to have long options, you’ll need to use the getopt utility. If not, I’d go for the getopts built-in, which I personally consider more user-friendly.

Sources:


If you liked this post, make sure you subscribe to receive notifications of new content by email or RSS feed.
Alternatively, feel free to follow me on Twitter or Google+.

Changing Linux Shell Prompt

I have been wondering how to customize the prompt in bash for some time now. I never had enough time and energy to look into that. Until now! So, let’s doo-ooo-ooo it!

It’s actually one of the simplest things. The prompt string is saved in an environment variable called $PS1 (prompt string). In order to change it you simply change the variable’s value and it’s done. So, let’s see …

First we want to know the actual value of the variable. We’ll print it out:

echo $PS1

This should give you something around \u@\h:\w\$ . If you compare it to the actual prompt astro@astro-desktop:~/MyBook$, you can easily guess what the escape sequences stand for.

  • \u — user name
  • \h — host name
  • \w — full path to current working directory

There are a lot more sequences, you can use. You can even color your prompt! For more information on this topic check out the links at the end of this post.

In order to change the prompt execute the following command:

export PS1="[his dudeness \u@\h:\w]\$ "

This will change your prompt string to something like

[his dudeness astro@astro-desktop:~]$ 

Now, we know how to customize the prompt string, but when you close the shell, it resets back to default. How to make the changes permanent? All you need to do is put the command into the .bashrc file in your home directory.

Actually, here are multiple prompt strings. $PS1 is the primary one. There is also a secondary prompt string that is used to indicate continuation of a multi-line command. For example:

astro@astro-desktop:~$ echo "abc\
> def\
> "
abcdef

In this case, the $PS2 is set to > .

Sources: