6

I have a bash script with a case statement in it:

case "$1" in 
    bash)
        docker exec -it $(docker-compose ps -q web) /bin/bash
        ;;
    shell)
        docker exec -it $(docker-compose ps -q web) python manage.py shell
        ;;
    test)
        docker exec -it $(docker-compose ps -q web) python manage.py test "${@:2}"
        ;;
esac

On the test command, I want to pass the default argument of apps, but only if the user didn't pass any arguments other than test to the bash script.

So, if the user runs the script like this:

./do test

it should run the command

docker exec -it $(docker-compose ps -q web) python manage.py test apps

However, if they run the script like this:

./do test billing accounts

it should run the command

docker exec -it $(docker-compose ps -q web) python manage.py test billing accounts

How can I test for the existence of arguments after the first argument?

1
  • 2
    [[ $# -ne 1 ]]... or, more correctly, (( $# != 1 ))
    – jasonwryan
    Commented Feb 1, 2016 at 21:44

5 Answers 5

8

I'd try to use bash variable substitution:

   test)
        shift
        docker exec -it $(docker-compose ps -q web) python manage.py test "${@-apps}"
        ;;

Other way is to check $* instead of $1:

case $* in 
    bash)
         ...
    test)
         docker exec -it $(docker-compose ps -q web) python manage.py test apps
         ;;
    test\ *)
         docker exec -it $(docker-compose ps -q web) python manage.py test "${@:2}"
         ;;
6
  • Did that edit mess it up? Should there be a : in "${@:-apps}"?
    – synic
    Commented Feb 1, 2016 at 22:32
  • 2
    @synic - the : will default even for a null valued second argument, and so doesnt answer the question asked. Without the : it will default only if there is no second argument.
    – mikeserv
    Commented Feb 1, 2016 at 22:34
  • 1
    The test of $@ doesnt test for two arguments (and the white space would need escaping in the pattern anyway).
    – mikeserv
    Commented Feb 2, 2016 at 8:30
  • @mikeserv Do you mean to change to $*?
    – Costas
    Commented Feb 2, 2016 at 8:36
  • Not exactly. See the comments on BinaryZebra's answer. It still doesnt test for two arguments. It looks for a concatenation of argument(s) that starts with the pattern test\ . And so if the first argument starts w/ test\ it means nothing. Both of you guys should be using ? anyway. But it isnt a robist test regardless.
    – mikeserv
    Commented Feb 2, 2016 at 12:12
2
case $1:$# in
(test:1)
    docker $(this is bad) python test apps;;
(test:$#)
    docker $(still bad) python "$@";;
(bash:$#)
    docker ...
esac
2

something like this would work well

if [ -z "$2" ]
  then
    echo "No argument supplied"
fi
4
  • 1
    I'd rather say [ "$#" -ne "2" ] , as you could very well pass an empty 2nd argument : myscript foo "" bar baz # has 4 args, and the arg $2 is empty Commented Feb 2, 2016 at 15:52
  • @OliverDulac - i dont think [ 2 -ne "$#" ] is a very useful test here. It negates every number of args but 2.
    – mikeserv
    Commented Feb 2, 2016 at 17:53
  • @mikeserv: the poster tests only the 2nd arg, and say "no argument" (without s). If there can be more than 2, then if [ "$#" -lt 2 ]; then echo "Not enough arguments supplied: you need at least 2"; fi will be fine. The point of my comment being still the same: testing for the 2nd argument's length doesn't tell you how many arguments were supplied... Commented Feb 2, 2016 at 18:28
  • @OliverDulac - true. The absence of a second argument does, though. [ "${2+:}" ] is probably the most simple way to robustly test for 2 or more arguments.
    – mikeserv
    Commented Feb 2, 2016 at 19:07
2

You can just reset your args however you want using set ...

case "$1" in 
    #...
    test)
        [ $# -lt 2 ] && set test apps
        docker exec -it $(docker-compose ps -q web) python manage.py $@
        ;;
esac
0
2

If arguments do not have spaces or newlines.
Transform the arguments into an string: "$*", and use that:

f(){ docker exec -it $(docker-compose ps -q web) "$@"; }

case "$*" in
    bash)       f /bin/bash                    ;;
    shell)      f python manage.py shell       ;;
    test)       f python manage.py test apps   ;;
    test\ ?*)   f python manage.py "$@"        ;;
esac

Using a function to manage code (not a variable) and remove repetition.

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .