Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check number of arguments passed to a Bash script

I would like my Bash script to print an error message if the required argument count is not met.

I tried the following code:

#!/bin/bash echo Script name: $0 echo $# arguments  if [$# -ne 1];      then echo "illegal number of parameters" fi 

For some unknown reason I've got the following error:

test: line 4: [2: command not found 

What am I doing wrong?

like image 591
Naftaly Avatar asked Sep 02 '13 08:09

Naftaly


People also ask

How do you count arguments in bash?

You can get the number of arguments from the special parameter $# . Value of 0 means "no arguments". $# is read-only. When used in conjunction with shift for argument processing, the special parameter $# is decremented each time Bash Builtin shift is executed.

How many arguments can be passed to bash script?

NUM} ) in the 2^32 range, so there is a hard limit somewhere (might vary on your machine), but Bash is so slow once you get above 2^20 arguments, that you will hit a performance limit well before you hit a hard limit.

What is $@ in bash?

bash [filename] runs the commands saved in a file. $@ refers to all of a shell script's command-line arguments. $1 , $2 , etc., refer to the first command-line argument, the second command-line argument, etc. Place variables in quotes if the values might have spaces in them.

Which command is used to print the total no of arguments passed at command line?

We are using the $# command to get the total number of arguments passed to the script file.


1 Answers

Just like any other simple command, [ ... ] or test requires spaces between its arguments.

if [ "$#" -ne 1 ]; then     echo "Illegal number of parameters" fi 

Or

if test "$#" -ne 1; then     echo "Illegal number of parameters" fi 

Suggestions

When in Bash, prefer using [[ ]] instead as it doesn't do word splitting and pathname expansion to its variables that quoting may not be necessary unless it's part of an expression.

[[ $# -ne 1 ]] 

It also has some other features like unquoted condition grouping, pattern matching (extended pattern matching with extglob) and regex matching.

The following example checks if arguments are valid. It allows a single argument or two.

[[ ($# -eq 1 || ($# -eq 2 && $2 == <glob pattern>)) && $1 =~ <regex pattern> ]] 

For pure arithmetic expressions, using (( )) to some may still be better, but they are still possible in [[ ]] with its arithmetic operators like -eq, -ne, -lt, -le, -gt, or -ge by placing the expression as a single string argument:

A=1 [[ 'A + 1' -eq 2 ]] && echo true  ## Prints true. 

That should be helpful if you would need to combine it with other features of [[ ]] as well.

Take note that [[ ]] and (( )) are keywords which have same level of parsing as if, case, while, and for.

Also as Dave suggested, error messages are better sent to stderr so they don't get included when stdout is redirected:

echo "Illegal number of parameters" >&2 

Exiting the script

It's also logical to make the script exit when invalid parameters are passed to it. This has already been suggested in the comments by ekangas but someone edited this answer to have it with -1 as the returned value, so I might as well do it right.

-1 though accepted by Bash as an argument to exit is not explicitly documented and is not right to be used as a common suggestion. 64 is also the most formal value since it's defined in sysexits.h with #define EX_USAGE 64 /* command line usage error */. Most tools like ls also return 2 on invalid arguments. I also used to return 2 in my scripts but lately I no longer really cared, and simply used 1 in all errors. But let's just place 2 here since it's most common and probably not OS-specific.

if [[ $# -ne 1 ]]; then     echo "Illegal number of parameters" >&2     exit 2 fi 

References

  • Bash Conditional Expressions
  • Conditional Constructs
  • Pattern Matching
  • Word Splitting
  • Filename Expansion (prev. Pathname Expansion)
  • Simple Commands
like image 55
konsolebox Avatar answered Oct 13 '22 14:10

konsolebox