1

I am trying to modify this script to accept multiple command line arguments but it keeps looping instead. It should allow the user to type more than one username in and then run.

#!/bin/bash
while [ $# -gt 0 ]; do #while arguments are greator than 1, do
        UNAME=$@ #set arg to var UNAME
        if [ -z ${UNAME} ]; then #if no argument is provided; then display this
            echo "Not enough arguments provided."
            echo "USAGE: $0 <user_name>"
            exit 1
        fi
        if grep ${UNAME} /etc/passwd >/dev/null; then #if UNAME exists then display info below
            echo "-------------------------------------------"
            echo "Username:       $(awk -F ':' -v uname=${UNAME} '$0 ~ uname {print $1}' /etc/passwd)"
            echo "User ID (UID):  $(awk -F ':' -v uname=${UNAME} '$0 ~ uname {print $3}' /etc/passwd)"
            echo "Group ID (GID): $(awk -F ':' -v uname=${UNAME} '$0 ~ uname {print $4}' /etc/passwd)"
            echo "User info:      $(awk -F ':' -v uname=${UNAME} '$0 ~ uname {print $5}' /etc/passwd)"
            echo "Home directory: $(awk -F ':' -v uname=${UNAME} '$0 ~ uname {print $6}' /etc/passwd)"
            echo "Command shell:  $(awk -F ':' -v uname=${UNAME} '$0 ~ uname {print $7}' /etc/passwd)"
            echo "-------------------------------------------"
        else #if UNAME is nonexistant then display this error message
            echo "-------------------------------------------"
            echo "\"${UNAME}\" does not exist."
            echo "-------------------------------------------"
        fi
done
        if [ $# -eq 0 ]; then #if num of args =0; then display this
                echo "Not enough arguments provided."
                echo "USAGE: $0 <user_name> [user_name] ..."
                exit 1
        fi
~
1
  • You're probably looking for shift (see help shift). Commented Apr 5, 2017 at 14:53

2 Answers 2

1

You are using a while loop, but not updating the index. It is easier to use a for loop, for example:

#!/bin/bash
for UNAME in "$@"
do
        if [ -z ${UNAME} ]; then #if no argument is provided; then display this
            echo "Not enough arguments provided."
            echo "USAGE: $0 <user_name>"
            exit 1
        fi
        if grep ${UNAME} /etc/passwd >/dev/null; then #if UNAME exists then display info below
            echo "-------------------------------------------"
            echo "Username:       $(awk -F ':' -v uname=${UNAME} '$0 ~ uname {print $1}' /etc/passwd)"
            echo "User ID (UID):  $(awk -F ':' -v uname=${UNAME} '$0 ~ uname {print $3}' /etc/passwd)"
            echo "Group ID (GID): $(awk -F ':' -v uname=${UNAME} '$0 ~ uname {print $4}' /etc/passwd)"
            echo "User info:      $(awk -F ':' -v uname=${UNAME} '$0 ~ uname {print $5}' /etc/passwd)"
            echo "Home directory: $(awk -F ':' -v uname=${UNAME} '$0 ~ uname {print $6}' /etc/passwd)"
            echo "Command shell:  $(awk -F ':' -v uname=${UNAME} '$0 ~ uname {print $7}' /etc/passwd)"
            echo "-------------------------------------------"
        else #if UNAME is nonexistant then display this error message
            echo "-------------------------------------------"
            echo "\"${UNAME}\" does not exist."
            echo "-------------------------------------------"
        fi
done

if [ $# -eq 0 ]; then #if num of args =0; then display this
        echo "Not enough arguments provided."
        echo "USAGE: $0 <user_name> [user_name] ..."
        exit 1
fi

In this case, variable UNAME is updated every iteration of the loop, with next provided argument.

Sign up to request clarification or add additional context in comments.

1 Comment

The if [ -z ${UNAME} ] block should probably be moved before the loop.
1

You can do that pretty easily with case and shift actually.
Here is a sample code:

#!/bin/bash
function main{

    # Main Stuff
}

while [[ $# -gt 1 ]]
do
    arg="$1"
    case $arg in
        -a|--argument-1)

            # Stuff for argument 1

            shift
        ;;
        -b|--argument-2)

            # Stuff for argument 2

            shift
        ;;
        -c|--argument-3)

            # Stuff for argument 3

            shift
        ;;
        --default)
            DEFAULT=YES
        ;;
        *)
            shift
        ;;
        esac
    shift
done
main
exit

Alternatively if you want special arguments which are always alone (for example --help / -h) You can do it like that:

#!/bin/bash
function main{

    # Main Stuff

}
if [ "${*}" = "--help" ] || [ "${*}" = "-h" ]; then

    # Help stuff

fi
while [[ $# -gt 1 ]]
do
    arg="$1"
    case $arg in
        -a|--argument-1)

            # Stuff for argument 1

            shift
        ;;
        -b|--argument-2)

            # Stuff for argument 2

            shift
        ;;
        -c|--argument-3)

            # Stuff for argument 3

            shift
        ;;
        --default)
            DEFAULT=YES
        ;;
        *)
            shift
        ;;
        esac
    shift
done
main
exit

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.