Bash Files with parameters
- Moose On The Loose
- Posts: 965
- Joined: Thu 24 Feb 2011, 14:54
[quote="GatorDog"]
I usually set all the variables to my defaults before parsing the parameters just in case the user may have a variable by that same name.
Also:
Code: Select all
display_time=10
output_dir="~/mysaveDir"
crossfade=10
Also:
Code: Select all
# Run the parameter through cut and use the -b1 to take just byte 1
FIRST=`echo "$1" | cut -b1`
# If it starts with a "-" then do as normal
if [[ "$FIRST" == "-" ]] ; then
case
...
esac
else
# Without a "-" is assumed to be the file to mung
FILENAME=$1
shift
fi
To keep my example as simple as possible I left this piece
of code out. It simply checks if there are an even number
of parameters on the command line. That is, each -option has
a matching parameter.
So with the approach I showed, it checks if there are any
parameters at all, and then that they are matched.
What this piece of code does: $(( $# % 2 )) != 0
borderlines on intentional error. If you need more certainty, you
could do a lookup of each option. Say you're running a video processing
script that takes several hours to run. It's a bummer to get to the
end of the process and find you mis-fired on an option
At the risk of being obvious, I'll mention that the "case" statement
used in this way also works well for parameters without the use
of "-xx" options.
rod
of code out. It simply checks if there are an even number
of parameters on the command line. That is, each -option has
a matching parameter.
So with the approach I showed, it checks if there are any
parameters at all, and then that they are matched.
Code: Select all
# Check if each option has a parameter passed with it.
# (ie check for even number of parameters on cmd line)
#
if [ $(( $# % 2 )) != 0 ] ; then
echo ; echo
echo "-----------------------------------------------"
echo "Check your command line. Option(s) specified "
echo "without matching parameter(s) (or vice-versa ;^)"
echo "-----------------------------------------------"
echo $0 $*
echo "-------------------"
exit
fi
These checks aren't bulletproof. But what they don't catch$# Is the number of command line arguments.
% This does division and returns the remainder. (Sometimes called modulo)
In this case, divide by 2. If the remainder
isn't zero, it's not an even number.
$(( )) Evaluate the enclosed expression and use it here.
!= Not equal to.
echo $0 $* This prints out the command and parameters you entered.
$0 Is the command name, in this case the name of the bash
script you are running.
$* Is all the parameters in a single string.
borderlines on intentional error. If you need more certainty, you
could do a lookup of each option. Say you're running a video processing
script that takes several hours to run. It's a bummer to get to the
end of the process and find you mis-fired on an option
At the risk of being obvious, I'll mention that the "case" statement
used in this way also works well for parameters without the use
of "-xx" options.
rod
- technosaurus
- Posts: 4853
- Joined: Mon 19 May 2008, 01:24
- Location: Blue Springs, MO
- Contact:
The most versatile method is probably: while $1 combined with case statements
You just evaluate each arg 1 at time by using shift ... add a second shift for 2 part args.
this is a wrapper template for a defaultfilemanager (to replace /usr/local/bin/rox)
You just evaluate each arg 1 at time by using shift ... add a second shift for 2 part args.
this is a wrapper template for a defaultfilemanager (to replace /usr/local/bin/rox)
Code: Select all
#!/bin/sh
#template to wrap other filemanagers for use in place of ROX-Filer
USERF=""
while ([ $1 ]) do
case $1 in
-b)ARGS=$ARGS" "$1" ";shift;USERF=1;;
--border=*)ARGS=$ARGS" "$1;USERF=1;;
-B)ARGS=$ARGS" "$1" "$2;shift;USERF=1;;
--bottom=*)ARGS=$ARGS" "$1;USERF=1;;
-c)ARGS=$ARGS" "$1" "$2;shift;USERF=1;;
--client-id=*)ARGS=$ARGS" "$1;USERF=1;;
-d)shift;ARGS=$ARGS" "$1;; #as far as I can tell -d is useless or should use dirname
--dir=*)ARGS=$ARGS" "`echo $1 |cut -d "=" -f2`;;
-D)ARGS=$ARGS" "$1" "$2;shift;USERF=1;;
--close=*)ARGS=$ARGS" "$1;USERF=1;;
-h|--help)ARGS=$ARGS" "$1;;
-l)ARGS=$ARGS" "$1" "$2;shift;USERF=1;;
--left=*)ARGS=$ARGS" "$1;USERF=1;;
-m)ARGS=$ARGS" "$1" "$2;shift;USERF=1;; #alternatively use file or xdg-*
--mime-type=*)ARGS=$ARGS" "$1;USERF=1;;
-n|--new)ARGS=$ARGS" "$1;USERF=1;;
-p)ARGS=$ARGS" "$1" "$2;shift;USERF=1;; #PCMan-FM has its own "pinboard"
--pinboard=*)ARGS=$ARGS" "$1;USERF=1;;
-r)ARGS=$ARGS" "$1" "$2;shift;USERF=1;;
--right=*)ARGS=$ARGS" "$1;USERF=1;;
-R)ARGS=$ARGS" "$1;USERF=1;;
--RPC)ARGS=$ARGS" "$1;USERF=1;;
-s)ARGS=$ARGS" "$1" "$2;shift;USERF=1;;
--show=*)ARGS=$ARGS" "$1;USERF=1;;
-S)ARGS=$ARGS" "$1;USERF=1;;
--rox-session)ARGS=$ARGS" "$1;USERF=1;;
-t)ARGS=$ARGS" "$1" "$2;shift;USERF=1;;
--top=*)ARGS=$ARGS" "$1;USERF=1;;
-u)ARGS=$ARGS" "$1" "$2;shift;USERF=1;;
--user)ARGS=$ARGS" "$1;USERF=1;;
-U)ARGS=$ARGS" "$1" "$2;shift;USERF=1;; #alternatively use defaultbrowser ...
--url=*)ARGS=$ARGS" "$1;USERF=1;;
-v|--version)ARGS=$ARGS" "$1;; #most file managers have this switch
-x)ARGS=$ARGS" "$1" "$2;shift;USERF=1;;
--examine=*)ARGS=$ARGS" "$1;USERF=1;;
*)ARGS=$ARGS" "$1;; #not a rox option, so probably ok to just pass it.
esac
shift
done
[ $USERF ] && /usr/local/apps/ROX-Filer/ROX-Filer $ARGS || defaultfilemanager $ARGS
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].
- technosaurus
- Posts: 4853
- Joined: Mon 19 May 2008, 01:24
- Location: Blue Springs, MO
- Contact:
Sorry about the lack of comments in the last example post, it had more context in the original post - but I am happy with rox so I never fully developed it.
Try these smaller bits to help understand
This will print each arg on a new line:
Explanation:
Shift removes the first arg (making $2 the new $1 ... etc also $# gets decremented)
The while $1 allows you to go through each variable until shift has shifted all of the args away.
The case statement - notice there are 2 basic templates - one is for the single arg, the other is for an arg that requires an additional parameter
By using shift, you can get your second parameter using $2 followed by a shift (the shift is needed to avoid trying to evaluate the second parameter as a standalone parameter)
Here is a simpler example based on the rox filers examplein this instance -f is a standalone parameter and -of requires a filename as a second parameter
One thing that could've made it more clear is that I could have left the shift inside the case statement rather than factoring it out...like this
-f)FORCE=TRUE;shift;;
-of)OUTPUTFILE=$2;shift;shift;;
( note that in some shells, shift 2 is the equivalent of shift;shift )
other than that some people like to use an equal sign instead of a second parameter, its case statement would be like:
myparam*)MYPARAM='echo $1 ¦cut -d "=" -f 2'
( use backtick instead of single quotes though .... that char is missing on my Droid )
Try these smaller bits to help understand
This will print each arg on a new line:
Code: Select all
while ([ $1 ]) do
echo $1
shift
done
Shift removes the first arg (making $2 the new $1 ... etc also $# gets decremented)
The while $1 allows you to go through each variable until shift has shifted all of the args away.
The case statement - notice there are 2 basic templates - one is for the single arg, the other is for an arg that requires an additional parameter
By using shift, you can get your second parameter using $2 followed by a shift (the shift is needed to avoid trying to evaluate the second parameter as a standalone parameter)
Here is a simpler example based on the rox filers example
Code: Select all
while ([ $1 ])
case $1 in
-f)FORCE=TRUE;;
-of)OUTPUTFILE=$2;shift;;
*)usage_function;;
esac
shift
done
One thing that could've made it more clear is that I could have left the shift inside the case statement rather than factoring it out...like this
-f)FORCE=TRUE;shift;;
-of)OUTPUTFILE=$2;shift;shift;;
( note that in some shells, shift 2 is the equivalent of shift;shift )
other than that some people like to use an equal sign instead of a second parameter, its case statement would be like:
myparam*)MYPARAM='echo $1 ¦cut -d "=" -f 2'
( use backtick instead of single quotes though .... that char is missing on my Droid )
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].
Just as an aside (maybe this is getting off topic), recent shells
have an alternative to the backtick `command substitution`.
ie. The $(...) syntax can replace the the backticks. It's claim to
fame is that it removes the single quote / backtick confusion and
arguably is much easier to read.
So
rod
have an alternative to the backtick `command substitution`.
ie. The $(...) syntax can replace the the backticks. It's claim to
fame is that it removes the single quote / backtick confusion and
arguably is much easier to read.
So
becomesmyparam*)MYPARAM='echo $1 ¦cut -d "=" -f 2'
( use backtick instead of single quotes though ...that char is missing on my Droid )
That's my story, and I'm sticking to it!myparam*)MYPARAM=$( echo $1 ¦cut -d "=" -f 2 )
rod