8

I need to update this bash function I use for doing things with git:

push() {
  a=$1
  if [ $# -eq 0 ]
    then
      a=$(timestamp)
  fi
  # ... do stuff
}

but I don't know how this line works

 if [ $# -eq 0 ]

I need to check for a first argument and then I need to check for a second argument.

So there will be 2 if statements.

How can I update this and how does this line work

 if [ $# -eq 0 ]
ChrisGPT was on strike
  • 127,765
  • 105
  • 273
  • 257
cade galt
  • 3,843
  • 8
  • 32
  • 48

2 Answers2

16

The $# part is a variable that contains the number of arguments passed to the script.

The conditional statement there checks the value of that variable using -eq and it's checking if the value is zero (as in no arguments were passed).

In order to check for two arguments, you can change (or add) that line to read like this:

 if [ $# -eq 2 ]
Lix
  • 47,311
  • 12
  • 103
  • 131
6

You could create a small script to look into how $# changes when you call the function with different numbers of arguments. For instance:

[Contents of "push.sh":]

push() {
    echo $#
}

echo "First call, no arguments:"
push
echo "Second call, one argument:"
push "First argument"
echo "Third call, two arguments:"
push "First argument" "And another one"

If you put this in a script and run it, you'll see something like:

-> % ./push.sh
First call, no arguments:
0
Second call, one argument:
1
Third call, two arguments:
2

This tells you that the value of $# contains the number of arguments given to the function.

The if [ $# -eq 0 ] part you can add to the script, and change the 0 to some other numbers to see what happens. Also, an internet search for "bash if" will reveal the meaning of the -eq part, and show that you could also use -lt or -gt, for instance, testing whether a number is less than or greater than another.

In the end, you'll likely want to use something like the following:

a=$1
b=$2

if [ $# -lt 1 ]
then
   a=$(timestamp)
fi

if [ $# -lt 2 ]
then
    b=$(second thing)
fi
joranvar
  • 490
  • 5
  • 9
  • Well, until this post I did not realize that `$#` was a variable. Why not use `<` or `>` like every other language I've seen. Why is this language so cryptic ? – cade galt Dec 06 '15 at 13:47
  • 1
    `<` and `>` do exist, but they are used for string comparisons (lexicographical ordering). I think they differ because strings and numbers are not "type safe" in bash, so [[ 10 < 2 ]] is true (in string ordering), but [[ 10 -lt 2 ]] is obviously false (the thing you would expect). – joranvar Dec 06 '15 at 13:50
  • Well in JS for example you can do `10 < 2` or `"10" < "2"` . You have to have some way to tell the interpreter if you have a number or a string. Hence the quotes to say hey ... this is a string. – cade galt Dec 06 '15 at 13:55
  • 1
    Having the operator determine what the operand is .... is absurdly crazy to say the least. – cade galt Dec 06 '15 at 13:57
  • That's one way to look at it. On the other hand, it would be quite tedious to have to put quotes around all arguments that are strings (like file names or command line options). But I agree, it can be confusing. – joranvar Dec 06 '15 at 14:03
  • JavaScript is a language that is "weakly typed", meaning you can put any type into the same variable using the `var` keyword. For example `var a = 1`. Bash does not even have a keyword or symbol to declare a variable it seems. You just go `a=1` or `a=foo`. How does it know that foo is not a variable. – cade galt Dec 06 '15 at 14:12
  • Bash knows that foo is not a variable because all variables in bash are prefixed by a $ character. Once you understand that, the "$#" variable makes more sense. Or "$!" for that matter (holds the PID of a previously backgrounded process). There are keywords to declare a variable in Bash, check out "declare" and "local". – user.friendly Aug 16 '17 at 04:08