0

I had written a help menu for reference about the usage of a shell script my_script.sh

echo $'\n\n'
echo $(printf '=%.0s' {1..100})
printf ' %.0s' {1..40}
echo "Welcome"
echo $(printf '=%.0s' {1..100})
echo $'\n'

arg=$1
echo "Input : $arg"
echo

if [[ arg -eq "-h" ]] || [[ arg -eq "-H" ]] || [[ arg -eq "-help" ]] || [[ arg -eq "-Help" ]] || [[ arg -eq "--h" ]] || [[ arg -eq "--H" ]] || [[ arg -eq "--help" ]] || [[ arg -eq "--Help" ]]; then
    echo "Help menu requested...."
    echo $'\n\n'
    echo $(printf '~%.0s' {1..100})
    printf ' %.0s' {1..43}
    echo "Help Menu"
    echo $(printf '~%.0s' {1..100})
    echo $'\n'
    exit 0
else
    echo "Executing a program...."
    ./another_script.sh
fi

When I execute `myscript.sh -h' (or any of the '-' prefixed option), it goes to the if condition, but any other argument doesn't. What am I doing wrong here? I'm new to bash scripts.

skrowten_hermit
  • 437
  • 3
  • 11
  • 28
  • Shouldn't you be using `$arg` (e.g. `"$arg" -eq "-h"`). You could use *getopts*. – CristiFati Sep 06 '18 at 12:41
  • 2
    Possible duplicate of [How do I parse command line arguments in Bash?](https://stackoverflow.com/questions/192249/how-do-i-parse-command-line-arguments-in-bash) – kenlukas Sep 06 '18 at 12:42
  • Also see [How to use Shellcheck](https://github.com/koalaman/shellcheck), [How to debug a bash script?](https://unix.stackexchange.com/q/155551/56041) (U&L.SE), [How to debug a bash script?](https://stackoverflow.com/q/951336/608639) (SO), [How to debug bash script?](https://askubuntu.com/q/21136) (AskU), [Debugging Bash scripts](http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_03.html), etc. – jww Sep 06 '18 at 13:11

3 Answers3

6

Two simple problems with your if:

But: I would recommend using getopts instead of string comparison. This would make the part more robust, taking care of different ordering of parameters, or when one letter parameters are combined into a single argument.

Karsten Koop
  • 2,475
  • 1
  • 18
  • 23
3

Unfortunately I do not know the exact reason why your code does not work, but I can offer you a quick fix: You can write "==" instead of "-eq" and prefix your variable "arg" with a dollar sign. Then your script should work fine.

Working example (GNU bash 4.4.19):

arg=$1

if [[ $arg == "-h" ]] || [[ $arg == "-H" ]]; then
  echo "Help!"
else
  echo "Stop!"
fi
  • 1
    Double brackets are better than single brackets. See: [What's the difference between [ and [[ in Bash?](https://stackoverflow.com/a/3427931/68587) – John Kugelman Sep 06 '18 at 13:03
  • Ok, thanks, @JohnKugelman! Then the problem should be with the comparison and the missing dollar sign, just as @KarstenKoop says. – David Fischak Sep 06 '18 at 13:09
  • Bash supports double equals but for portability you should use the POSIX single equals sign. – tripleee Sep 10 '18 at 04:24
2
  1. the -eq operation is only used for comparing numbers.
  2. To compare strings uses the operation =
  3. You forgot $ sign for variables arg in Bash, should be $arg
  4. When we use variables in Bash, we should better use double quote.
  5. use @() for multiple strings comparison.

so the if conditions [[ arg -eq "-h" ]] should be [[ "$arg" = "-h" ]]

When comparing a variable with multiple strings, we can use [[ "$arg" = @(-h|-H|--help|--HELP|--h|--H|-help|--HELP) ]].

if [[ "$arg" = @(-h|-H|--help|--HELP|--h|--H|-help|--HELP) ]]; then
     echo "Help menu requested...."
     echo $'\n\n'
     echo $(printf '~%.0s' {1..100})
     printf ' %.0s' {1..43}
     echo "Help Menu"
     echo $(printf '~%.0s' {1..100})
     echo $'\n'
     exit 0
else
     echo "Executing a program...."
     ./another_script.sh
fi

In addition, we can use boxes(boxes - Command line ASCII boxes unlimited! ) to generate a comment box

cat <<EOF | boxes -a c -d shell -p a5 -s 30x9
HELP MENU

bla bla
EOF

output:

########################################
#                                      #
#                                      #
#              HELP MENU               #
#                                      #
#               bla bla                #
#                                      #
#                                      #
########################################
Feng
  • 3,592
  • 2
  • 15
  • 14
  • That was really helpful. How do I add a null string to `[[ "$arg" = @(-h|-H|--help|--HELP|--h|--H|-help|--HELP) ]]`? – skrowten_hermit Sep 07 '18 at 09:09
  • `[[ "${arg:=-h}" = @(-h|-H|--help|--HELP|--h|--H|-help|--HELP) ]]` – Feng Sep 07 '18 at 10:31
  • `"${arg:=-h}"` means to set the default value of variable `arg` to `-h` if `arg` is unset or empty – Feng Sep 07 '18 at 10:32
  • The `@(...)` syntax is a Bash extension which requires `shopt -s extglob` – tripleee Sep 10 '18 at 04:27
  • @Feng I mean how do I add something like `-z "$arg"` to `[[ "$arg" = @(-h|-H|--help|--HELP|--h|--H|-help|--HELP) ]]`? – skrowten_hermit Sep 12 '18 at 09:53
  • 1
    @skrowten_hermit do you mean `[[ -z "$arg" || "$arg" = @(-h|-H|--help|--HELP|--h|--H|-help|--HELP) ]]`? – Feng Sep 12 '18 at 10:24
  • Okay. This will do as well if it's valid. But, is there nothing like a null value or something, which I can add to `@(-h|-H|--help|--HELP|--h|--H|-help|--HELP)`? – skrowten_hermit Sep 12 '18 at 10:30
  • 1
    yeah, `[[ "${arg:=-h}" = @(-h|-H|--help|--HELP|--h|--H|-help|--HELP) ]]` this is what you want. `${arg:=-h}` means if `arg` is empty or null then set `arg` to `-h` otherwise `arg` is the original value. So we don't need to add something like `NULL` or `undefined` to `@(...)` – Feng Sep 12 '18 at 10:36
  • @tripleee `shopt -s extglob` means that we can use `@(...)` as parameters, like `ls @(...|...)`. But in testing expressions, like `[[ "foo" = @(...|...) ]]`, we don't need to enable this option. – Feng Sep 12 '18 at 10:45
  • Oooh, TIL! Thanks for following up. – tripleee Sep 12 '18 at 14:04