So, I am trying to write a script to
1.) Create a new directory with the name the user has specified
2.) Download files from a remote location into the new directory
3.) Append a port to a file in the new directory
What I have now is
OPTIND=1
while getopts "hpnm:" opt; do
case "$opt" in
h)
show_help
exit 0
shift
;;
p) port="*@"
shift
/home/servers/zombies/"$server_name"/server.properties >> port: "$@"
;;
n) server_name="$*"
shift
mkdir /home/ecb/servers/zombies/"$*"
;;
m) map_name="$*"
shift
rsync -azvP username@host:/home/downloads/zombies/"$*" /home/servers/zombies/"$server_name"/
;;
esac
done
When I run the script it interprets "-n Test -m test -p 1234" as "Test test 1234". How would I separate the arguments?
Don't shift
. That will confuse getopts
, since you are modifying the argument list while it is working.
If an option takes an argument, put a colon after the character in the argument vector. In your case, -p
, -n
and -m
all take arguments, not just -m
. So your invocation should be:
while getopts "hp:n:m:" opt; do
To refer to the option argument, use $OPTARG
. getops will put the argument in that variable (provided you told getopts that the option takes an argument).
When getopts finishes, OPTIND
will be the index of the first positional argument. At this point, if you want, you can shift away all of the consumed arguments:
shift $((OPTIND-1))
Or you can scan them using bash
's subsequence notation:
for arg in "${@:OPTIND}"; do
It is usually not a good idea to act on options immediately. Rather, you would normally save each argument to a variable and process the variables when option parsing is finished. There are a couple of reasons:
You might detect an error after the first option has been recognized. In that case, you would normally want to produce an error message without altering the state of the world.
Normally, there is no specified order for options (which is why they are identified with option letters, rather than being positional). It's often the case that the actions are better performed in a specific order.
Options are, by definition, optional. But you don't know that an option is unspecified until you reach the end of the list. If the option has a default value, or if the non-specification of the option affects the behaviour of your script, you probably want to know about it before you start doing things.
It is normally not necessary to initialize OPTIND
, since bash
does that automatically when it creates a new execution environment.