I'm writing a bash script that will
It looks like:
[[ "${1}" = "-h" || "${1}" = "--help" ]] && echo -e "somehelp"
[[ "${1}" = "echo" ]] && echo ${*:2}
[[ "${1}" = "emerge" ]] && emerge -uDN ${*:2}
some-magic-here
Now, if I do
myscript emerge -a whatever whatever2 --option
it would run
emerge -uDN -a whatever whatever2 --option
But, in case that "whatever" is a string containing *
, such as
myscript emerge -uDN -a whatever/* whatever2 --option
I'd want it to run
emerge -uDN -a $(eix -u --only-names whatever/*) whatever2 --option
instead. Any tips?
First, if you are going to pass *
to the script, you must prevent expansion by the shell on the command line. The simplest way is to quote it:
myscript emerge -a 'whatever/*' whatever2 --option
Since you are already using the [[
operator, note: the following is a bash only solution and not portable to sh. To determine if $3 contains a *
you can use the =~
operator:
[[ "${1}" == "emerge" ]] && {
[[ "$3" =~ "*" ]] && \
emerge -uDN $2 $(eix -u --only-names $3) ${*:4} || \
emerge -uDN ${*:2}
}
You can also rewrite the compound commands into nested if-else
statements if the logic gets a bit murky. Give it a try and let me know if you have any issues.
You mention the command line:
myscript emerge -uDN -a whatever/* whatever2 --option
The only ways myscript
will see the *
in its argument list is if there is no subdirectory whatever
under the current directory, or it is an empty directory (strictly: if it contains any files, the names all start with .
), and in either case, you don't have shopt -s nullglob
set. If those conditions aren't met, the shell invoking myscript
will replace the *
(in)appropriately and myscript
will not see the *
. (Of course, if you quote the argument — "whatever/*"
or 'whatever/*'
, then myscript
will also see the *
metacharacter, regardless of nullglob
and the presence or absence of a whatever
subdirectory.)
It is not clear whether the *
needs to be replaced only when it follows the -a
option, or if it should be replaced in any argument whatsoever. I will assume that all arguments need to be replaced; it is not very different if it is only the argument after the -a
that should be replaced.
Without the code to handle whatever/*
, the command looks like:
[[ "${1}" = "emerge" ]] && exec emerge -uDN "${@:2}" || exit 1
Differences:
The exec
is optional but guarantees that nothing after the emerge
command will be executed (unless the emerge
command can't be found, in which case the || exit 1
ensures nothing else is executed).
Use "$@"
to preserve the arguments as presented to your script. Without double quotes, there's no difference between $@
and $*
. Inside double quotes, "$*"
generates a single string, but "$@"
generates each argument as passed to the script. The "${@:2}"
notation does this for the second up to the last argument.
To handle the *
for any argument, we need to detect the *
. This is going to be easiest if we use arrays.
The array arglist
will contain the arguments to be passed to the emerge
command. We need to iterate over the arguments to the script, checking for appearances of *
:
arglist=( "-uDN" )
for arg in "${@:2}"
do
case "$arg" in
(*\**) arglist+=( $(eix -u --only-names "$arg") );;
(*) arglist+=( "$arg" );;
esac
done
exec emerge "${arglist[@]}"
exit 1
Note that this assumes that eix
will expand metacharacters ( *
to be precise), rather than relying on the shell to do so. It also assumes, as the question assumes, that there are no spaces in the names generated by eix
. If there are any, the $(…)
notation will split the names at the spaces (or tabs, or newlines, …).
This code would be best handled as the body of the then
clause in
if [[ "${1}" = "emerge" ]]
then
…
fi
This would be clearer than trying to squeeze all that code onto a single line (which could be done, but there is no point in doing so and many points to not doing so).
Here's a clue:
#!/bin/sh
x="bbbccc" # Put different strings in here, and see what happens
case "$x" in
*\**)
echo "Yes"
;;
*)
echo "No"
;;
esac
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.