Bash Files with parameters

For discussions about programming, programming questions/advice, and projects that don't really have anything to do with Puppy.
Message
Author
Bruce B

#16 Post by Bruce B »

jpeps,

Incredible!

I hate to admit it, but I didn't know arg was a bash keyword. Not knowing it, I looked at the for arg and went, huh?

Thanks

Bruce

~

User avatar
Moose On The Loose
Posts: 965
Joined: Thu 24 Feb 2011, 14:54

#17 Post by Moose On The Loose »

[quote="GatorDog"]

Code: Select all

display_time=10
output_dir="~/mysaveDir"
crossfade=10
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

# 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

User avatar
GatorDog
Posts: 138
Joined: Tue 12 Sep 2006, 16:43

#18 Post by GatorDog »

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.

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
What this piece of code does: $(( $# % 2 )) != 0
$# 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.
These checks aren't bulletproof. But what they don't catch
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

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#19 Post by technosaurus »

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)

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].

Bruce B

#20 Post by Bruce B »

Come on guys. Some of us only have a 95 IQ

I'm afraid I'll have to get married to technosaurus last post. A lifetime anyway to figure what he is saying. That's sort of like marriage isn't it?


~

User avatar
GatorDog
Posts: 138
Joined: Tue 12 Sep 2006, 16:43

#21 Post by GatorDog »

this is a wrapper template for a defaultfilemanager (to replace /usr/local/bin/rox)
Yep, that looks pretty good too :wink:

rod

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#22 Post by technosaurus »

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:

Code: Select all

while ([ $1 ]) do
echo $1
shift
done
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 example

Code: Select all

while ([ $1 ]) 
case $1 in
  -f)FORCE=TRUE;;
  -of)OUTPUTFILE=$2;shift;;
  *)usage_function;;
esac
shift
done
in 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 )
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].

User avatar
GatorDog
Posts: 138
Joined: Tue 12 Sep 2006, 16:43

#23 Post by GatorDog »

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
myparam*)MYPARAM='echo $1 ¦cut -d "=" -f 2'
( use backtick instead of single quotes though ...that char is missing on my Droid )
becomes
myparam*)MYPARAM=$( echo $1 ¦cut -d "=" -f 2 )
That's my story, and I'm sticking to it!
rod

Post Reply