Table of Contents
How to pass and store arguments to shell script? How to parse input arguments inside shell script? How to pass arguments to a function inside shell script in bash? How to read command line arguments in shell script?
In this tutorial we will cover these questions covering bash script arguments with multiple scenarios and examples. I will try to be as detailed as possible so even a beginner to Linux can easily understand the concept.
How input arguments are parsed in bash shell script
Generally we pass arguments to a script using this syntax
~]# ./eg_1.sh first second third fourth
Now to store all these arguments inside the script in a single variable we can use "
But to store these arguments in individual variable, you can assign the values based on the numerical position of the input argument. You can check this sample script where I am storing upto 4 arguments in individual variables. You can use any names for the variable, I have used these just for better understanding. Here any argument after 4th place will be ignored.
Let,s execute this script:
~]# ./eg_1.sh first second third fourth Input argument list: First argument: first Second argument: second Third argument: third Fourth argument: fourth
So as expected the script has successfully stored the input arguments and printed them on the screen
Method 1: Parse input arguments with if condition and while loop
In this example we will use if condition to parse the input arguments and perform respective action. Here I have written a small script which is expected to collect following input arguments
--helpshould print the usage function
--rpm [RPM]will just print the provided rpm name on the console
--sleep [VAL]will just [print the sleep value on the console
Let us understand this script:
Line 12are my usage function which should be clear enough.
Line 14I am using a while loop if
[ ! -z "$1" ]condition which will make sure that our if condition will continue to be checked until there are no further input arguments. This is a more robust solution rather than assigning individual arguments to a variable as here we don't have to worry about the order of input arguments.
Line 15will check for
-hfor the first input argument and if found it will print the usage function content from
Line 17will check for
--rpmin the provided first argument and if found store the second input argument with
Line 19will print the content of
Line 20is used to
shiftthe position so that we don't have to use
$3next time as that may be confusing and alot of things can go wrong so shift is very important when dealing with input arguments
Line 21will check for
--sleepin the first input argument and if found the second input argument will be stored in
Line 23will print the
SLEEPvalue collected at
Line 24is again important as we will perform a
28will be executed if no matching input arguments found by printing the
Line 29again contains
shiftto make sure the script doesn't end up in an infinite loop
Line 30will end the
You can execute the script by shuffling the order of input arguments and it should still work. Although I am not a big fan of this method as it is very messy and I would prefer case over if condition if the number of input arguments is more than 3.
~]# ./eg_1.sh -r kernel -s 10 rpm name is kernel sleep value is 10 ~]# ./eg_1.sh -s 10 -r kernel sleep value is 10 rpm name is kernel
When should we use "shift" when working with input arguments
- You may get confused as in when should you use
shiftwhen working with input arguments.
- If your input arguments don't expect a value for the respective argument then you can ignore shift, as you can see I didn't used
--helpin the above script
- If you are using a loop to parse through your argument then you have to use shift depending upon your requirement. If your input arguments don't expect a value then a shift is required near the end of the loop only.
- Consider a scenario wherein you have to collect ~10 input arguments and some of them may expect input value for respective arguments so it would be very hard to manage with
$1, $2 ..to collect the input arguments
- So we use
whileloop with shift operation so that the loop will iterate over the available input arguments
whileloop we will always deal with
$2for the input arg and arg's value so the solution is cleaner
- Once you have the value you can perform shift so we again start from
- If you have a requirement to only collect 2-3 input arguments you can avoid shift if it feels too complicated for you.
Method 2: Parse input arguments with case statement and while loop
In this example we will use case statement with
while loop to check for input arguments. As you can see the script looks much cleaner compared to the one with
while [ ! -z "$1" ];do case "$1" in -h|--help) show_usage ;; -r|--rpm) shift RPM_NAME="$1" echo "rpm name is $RPM_NAME" ;; -s|--sleep) shift SLEEP="$1" echo "sleep value is $SLEEP" ;; *) echo "Incorrect input provided" show_usage esac shift done
I don't think I need to again explain this part of the script line by line. Here I have switched the position of shift so now if
$1 matches the condition such as
--rpm then I do the
shift so now second argument has become the first for me so I store the first argument into
RPM_NAME and print the same
We can execute the script and verify in any possible order:
~]# ./eg_1.sh -s 10 -r kernel sleep value is 10 rpm name is kernel ~]# ./eg_1.sh -r kernel -s 10 rpm name is kernel sleep value is 10
Handling exceptions and errors with bash script arguments
Scenario 1: Missing value for input argument
In all the examples above we also worked on success use case. But what if you were expecting an input argument with a value but the user forgot to pass a value? In such case your entire loop can break. Let's use the above case statement to demonstrate this:
~]# ./eg_1.sh -r -s 10 rpm name is -s Incorrect input provided Usage: ./eg_1.sh [options [parameters]] Options: -r|--rpm [rpm_name], Print rpm name -s|--sleep, Provide the value to sleep -h|--help, Print help
As expected I did not gave a value for
-s was considered as the rpm name and then 10 was considered as an input argument. Since we have not defined
10 as a supported input arg, the script failed and printed the
So it is very important that we handle such error scenarios. Now the handling may vary from case to case. For example if you are only expecting an integer as a value for some input argument then you can add that check, let me show you some examples:
In this script I have added below addition check:
[[ $RPM_NAME =~ ^- ]] && echo "$RPM_NAME is not a proper value for -r|--rpm" && show_usage [[ $SLEEP =~ ^- ]] && echo "$SLEEP is not a proper value for -s|--sleep" && show_usage
So we know that all our input arguments start with hyphen so if the value of input argument starts with hyphen then it means that a value was not provided.
Let's test this script, and it works perfectly this time:
~]# ./eg_1.sh -r -s 10 -s is not a proper value for -r|--rpm Usage: ./eg_1.sh [options [parameters]] Options: -r|--rpm [rpm_name], Print rpm name -s|--sleep, Provide the value to sleep -h|--help, Print help
Scenario 2: Count input arguments list
Another possible scenario of failure would be where we expect only 2 input arguments but the user gives more then 2 input arguments, so we should add a check for supported arguments:
Here we will count the list of minimum supported arguments and if it is greater than 3 then print a message with usage section and exit:
if [ $# -gt 3 ];then echo "Only 3 input arguments supported" show_usage exit 1 fi while [ ! -z "$1" ];do case "$1" in -h|--help) show_usage ;; <output trimmed>
Let's verify our script:
# ./eg_1.sh -r -s 10 -a Only 3 input arguments supported Usage: ./eg_1.sh [options [parameters]] Options: -r|--rpm [rpm_name], Print rpm name -s|--sleep, Provide the value to sleep -h|--help, Print help
Scenario 3: When script is executed without any argument
Similarly what if the user executes the script without any input argument? In such case also we should exit by showing the usage section:
if [[ $# -gt 3 ]] || [[ $# -eq 0 ]];then echo "Either 0 or more than 3 input arguments provided which is not supported" show_usage exit 1 fi while [ ! -z "$1" ];do case "$1" in -h|--help) show_usage ;; <output trimmed>
So I have added one more check in the same if condition, let's verify this script:
~]# ./eg_1.sh Either 0 or more than 3 input arguments provided which is not supported Usage: ./eg_1.sh [options [parameters]] Options: -r|--rpm [rpm_name], Print rpm name -s|--sleep, Provide the value to sleep -h|--help, Print help
Similarly you can add multiple checks based on your requirement.
In this tutorial I showed you different examples to executed input arguments with bash scripts. You can use similar logic when handling input arguments for functions in shell scripts. If you have any custom scenario which you need help with then you can use the comment box below to give as much detail as possible and I will try to help you out.
Lastly I hope the steps from the article to learn bash script arguments on Linux was helpful. So, let me know your suggestions and feedback using the comment section.