I am trying to get a bash script that g开发者_C百科enerates JSDoc for given parameters like this
./jsdoc.sh file.js another.js maybe-a-third.js
I am getting stuck on how to pass an unknown quantity of parameters to the next shell command.
(also, don't know how to check if param exists, only if not exitst if [ -z ... ]
)
This code works for up to two parameters, but obviously not the right way to go about it...
#!/bin/bash
# would like to know how to do positive check
if [ -z "$1" ]
then echo no param
else
d=$PWD
cd ~/projects/jsdoc-toolkit/
# this bit is obviously not the right approach
if [ -z "$2" ]
then java -jar jsrun.jar app/run.js -a -t=templates/jsdoc/ $d/$1
else java -jar jsrun.jar app/run.js -a -t=templates/jsdoc/ $d/$1 $d/$2
fi
cp -R out/jsdoc $d
fi
Any other pointers of how I could achieve this would be appreciated.
Edit: Updated script according to @skjaidev's answer - happy days ;)
#!/bin/bash
d=$PWD
for i in $*; do
params=" $params $d/$i"
done
if [ -n "$1" ]; then
cd ~/projects/jsdoc-toolkit/
java -jar jsrun.jar app/run.js -a -t=templates/jsdoc/ $params
cp -R out/jsdoc $d
fi
$* has all the parameters. You could iterate over them
for i in $*;
do
params=" $params $d/$i"
done
your_cmd $params
To handle arguments that contain whitespace, use "$@"
to iterate, and store the for later use in an array.
#!/bin/bash
if (( $# == 0 )); then
echo "usage: $0 file ..."
exit
fi
dir=$(pwd)
declare -a params
for file in "$@"; do params+=( "$dir/$file" ); done
cd ~/projects/jsdoc-toolkit/
java -jar jsrun.jar app/run.js -a -t=templates/jsdoc/ "${params[@]}"
cp -R out/jsdoc "$dir"
-n
is the inverse of -z
, and "$@"
is the canonical way to pass all parameters on to a subcommand. This and more can be found via man bash
.
Bash-specific features (arrays in this case) can be avoided through careful use of the IFS
variable and the special $@
parameter.
#!/bin/sh
dir=$(pwd)
NEW_ARGV=""
# carefully modify original arguments individually and separate them with newlines
# in a new variable (in case they contain spaces)
NEW_ARGV=""
for var in "${@}"
do
NEW_ARGV="${NEW_ARGV}
${dir}/${var}"
done
SV_IFS=${IFS}
# temporarily set IFS to a newline as per NEW_ARGV setup
IFS="
"
# reset $@ with the modified newline-separated arguments
set -- ${NEW_ARGV}
IFS=${SV_IFS}
# for testing, demonstrate each param is preserved
c=0
for i in "${@}"
do
c=`expr ${c} + 1`
echo "args-via-var #${c}: \"${i}\""
done
cd ~/projects/jsdoc-toolkit/
java -jar jsrun.jar app/run.js -a -t=templates/jsdoc/ "${@}"
cp -R out/jsdoc "${dir}"
It's not necessary to reset $@
, but doing so avoids messing with IFS
in multiple places. Without going through $@
one must set IFS
everywhere one expands $NEW_ARGV
.
Those with an eye for detail will note that this method does not preserve parameters when they contain newlines. It would be possible to use any control character in place of newline, except of course NUL
, and perhaps ASCII FS (file separator, aka ctrl-\
) would be both meaningful and very unlikely to occur in a valid filename.
精彩评论