1

I am building a script (linux bash) where I need to pass a certain number of arguments, it can be 7 or 8 arguments.

If I pass 7 arguments I will do it like this:

my_script.sh

!/bin/bash

arg1=$1
arg2=$2
arg3=$3
arg4=$4
arg5=$5
arg6=$6
arg7=$7
#Do other stuff after this

and I run it like this: ./my_script.sh 1 2 3 4 5 6 7

I want to be able to add an optional 8th parameter into this script. So the idea is to run the script with this 8th parametes sometimes and the rest of the time only with 7 parameters. How can I do this?

fr0zt
  • 733
  • 4
  • 12
  • 30
  • You can check if $8 is set I think... Not really sure – ciao1092 Oct 20 '22 at 13:30
  • Yes, but if it's not set will I get an error? Not sure if that's the best approach – fr0zt Oct 20 '22 at 13:33
  • Why are you doing this? What is "other stuff" doing that requires it to use `${arg7}` instead of `$7`. It sounds like you have an XY problem that would be clarified by more detail. In general, you can just reference `$8`. If it wasn't passed, that will be the empty string. If you want a default, use `${8-default}` or `${8:-default}`. It's not clear what you're trying to do. – William Pursell Oct 20 '22 at 13:55

4 Answers4

2

Another thought. After you assign the first 7 args, use shift 7 to clear them from the positional parameters. Then, any extra parameters are in "$@" and the number is in $#

arg1=$1
arg2=$2
arg3=$3
arg4=$4
arg5=$5
arg6=$6
arg7=$7

shift 7

echo "There are $# extra parameters"
for arg in "$@"; do
    echo "-> $arg"
done
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
1

You could do something like this:

if [[ $8 != '' ]]
then
  # do something
fi

Also, if you do

arg8=$8

and if there is no eighth arg, arg8 will just remain empty.

ciao1092
  • 98
  • 6
1

You could check the value of $#, something like.

#!/usr/bin/env bash

if (($# == 8)); then
  printf '%d arguments given\n' "$#"
elif (($# > 8)); then
  printf '%d is greater than 8\n'  "$#"
elif (($# < 8)); then
  printf '%d is  Less than 8\n' "$#"
fi

To test that script.

my_script {1..8}

Output

8 arguments given

my_script {1..87}

Output

87 is greater than 8

my_script {1..7}

Output

7 is  Less than 8
Jetchisel
  • 7,493
  • 2
  • 19
  • 18
  • So, is there a way for me to handle and get a variable number of parameters? – fr0zt Oct 27 '22 at 08:28
  • The `"$#"` shows the number of args/parameters, is that what you're asking? – Jetchisel Oct 27 '22 at 08:34
  • I can store all arguments like this. for arg in "$@"; do echo "store all characters in a var. as a string". done. IS there a way to store all arguments in arguments var like this: arguments= arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8. All in one line – fr0zt Oct 27 '22 at 08:46
  • `for arg in "$@"; do arguments+=("$args") ; done` and check the vallue `declare -p arguments`, something like that? – Jetchisel Oct 27 '22 at 08:51
  • IS there a way for us to chat? I am doing like this: for arg in "$@"; do arguments+=("$args") done. echo "$arguments". But its not working. Its only capturing first argument – fr0zt Oct 27 '22 at 09:02
  • it is working like this: for arg in "$@"; do arguments+="$args" done. echo "$arguments" thanks – fr0zt Oct 27 '22 at 09:11
  • the whole args is an array, so expand it like `printf '%s\n' "${arguments[@]}"` – Jetchisel Oct 27 '22 at 10:51
1

That's a lot of arguments. Are they all necessary every time? Can you default some?

Basically, I see three primary cases for this.

  1. You have a list of fixed-position required arguments. If they are all truly required, and you can never assume default values for any of them, then positional is actually good as it simplifies your coding... but as soon as you introduce optional arguments, you should seriously start considering getopts.

  2. if you have exactly and only one optional argument, then just assign arg8=$8 and don't worry about it - but as soon as you have two, then you really need to think about the implications. If you need $9 but don't really care about $8 then you have to pass in a dummy value to fill $8 for there to be a $9. Don't go there.

  3. in most cases, unless a script is really simple (and mine almost never are), you should use getopts.

Let's say that you're writing a telecom script that sums minutes of use. The script absolutely requires 3 arguments from user - for our example, say you need $state, $mmyy and $stream to identify input files by state and month/year, and local or long-distance. (You could always just pass that as $STMMYYLT or some such to reduce it to one argument if that's your taste, but generally, let a thing be a thing.)

With those, you can run it and get total minutes. Great.

But sometimes you need them broken out by account. Sometimes means an option argument. -s for --summarize changes the accumulation and output.

Sometimes you only need a specific account. You could always pipe the result through a grep or something, but if you can skip processing of 99.999% of a multi-gigabyte file by adding one more argument, I think that's worth it, so let's add a -a for --account option. If you give it an account, it will ignore everything else.

When designing, always thing in terms of the help screen that gives you usage instructions. It will really help your design to think of these things ahead of time. (Maybe that means a -h for --help is a good idea too...)
There are some guidelines on standard formatting such as this post or this wiki.

So, if you feed it an unacceptable set of arguments (including none), or specifically request --help, it should spit out a usage message and exit.

This gives you a guide for writing code. You can edit it as you figure out more.

Paul Hodges
  • 13,382
  • 1
  • 17
  • 36