Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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?

share|improve this question
1  
[[ $# -ne 1 ]]... or, more correctly, (( $# != 1 )) – jasonwryan Feb 1 at 21:44
up vote 7 down vote accepted

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}"
         ;;
share|improve this answer
    
Awesome, I like that one. – synic Feb 1 at 22:29
    
Did that edit mess it up? Should there be a : in "${@:-apps}"? – synic Feb 1 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 Feb 1 at 22:34
1  
The test of $@ doesnt test for two arguments (and the white space would need escaping in the pattern anyway). – mikeserv Feb 2 at 8:30
    
@mikeserv Do you mean to change to $*? – Costas Feb 2 at 8:36
case $1:$# in
(test:1)
    docker $(this is bad) python test apps;;
(test:$#)
    docker $(still bad) python "$@";;
(bash:$#)
    docker ...
esac
share|improve this answer

something like this would work well

if [ -z "$2" ]
  then
    echo "No argument supplied"
fi
share|improve this answer
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 – Olivier Dulac Feb 2 at 15:52
    
@OliverDulac - i dont think [ 2 -ne "$#" ] is a very useful test here. It negates every number of args but 2. – mikeserv Feb 2 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... – Olivier Dulac Feb 2 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 Feb 2 at 19:07

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
share|improve this answer

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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.