LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software
User Name
Password
Linux - Software This forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.

Notices


Reply
  Search this Thread
Old 03-16-2012, 06:51 PM   #1
dcparris
LQ Newbie
 
Registered: Dec 2011
Location: Charlotte, NC
Distribution: Debian, Kbuntu, CentOS
Posts: 13
Blog Entries: 1

Rep: Reputation: 0
Problem With Arguments Test in Bash Script


I'm still a bit of a novice when it comes to bash scripting, and am having problems processing arguments from the command line. I tend to run my script as:
Code:
./myscript file1 file2 or ./myscript action file1 file2
If I run the script with no action - just the files - the script runs the default action.

I want to say:
(1) if one or more files are listed, with no action, then process with default action
(2) if an action is given, along with one or more files, then process the files with this action
(3) action, if given must be $1

Can anyone help?

My current incarnation looks like this:
Code:
if [ -f "$1" -o -d "$1" ]   # if this is a file or directory
    then
        filelist="$@"
        action1          # default action, process files
    elif [ ! -f "$1" -a ! -d "$1" ]  # if it is NOT a file AND not a directory, it's an action.
    then
        action="$1"
        filelist="$@"
        if [ $action == "action1" ]  # default action when called explicitly
            then
                action1              # calls the function to process the files
            elif [ $action == "action2" ]   # performs opposite action on files
            then
                action2
# the rest of these are just helpful actions, but do not actually process files
            elif [ $action == "action3" ]
            then
                action3
            elif [ $action == "action4" ]
            then
                action4
            elif [ $action == "action5" ]
            then
                action5
            elif [ $action == "action6" ]
            then
                action6
            else    
                echo "$action is invalid"
        fi
    else
        echo "Not an option"
fi
Two problems:
(1) Even though I have checked my arguments here, I still have to strip $1 from those functions that do process the files anyway.
(2) The action1 function works great, but the action2 function breaks, even though it processes the files in reverse from action1.

This part of action1 and action2 are exactly alike:
Code:
action()
{
for f in $filelist  # processes $1 (the action), along with the files.
do
    if [ -f "$f" -o -d "$f" ]  # this is to prevent processing $1
Is getopts a better approach?

Thanks!

Last edited by dcparris; 03-16-2012 at 06:56 PM. Reason: Clarify question
 
Old 03-17-2012, 04:05 AM   #2
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405
Hi,

Quote:
Originally Posted by dcparris
(1) Even though I have checked my arguments here, I still have to strip $1 from those functions that do process the files anyway.
You can use shift to get rid of the first argument (simplified):
Code:
#!/bin/bash

if [ -f "$1" -o -d "$1" ]
then
   action="default action"
   filelist="$@"
else
   action="$1"
   shift           # strip first argument
   filelist="$@"
fi

echo $action
echo $filelist

exit 0
Quote:
2) The action1 function works great, but the action2 function breaks, even though it processes the files in reverse from action1.
Maybe this will work (simplified):
Code:
#!/bin/bash

doAction() {
   Action="$1"    # store $1 (= action) in human readable variable
   Files="$2"     # store $2 (= file(s)) in human readable variable
   # the next part is a case/esac construct
   case ${Action} in
     action1) echo "do action 1 on $Files";;
     action2) echo "do action 2 on $Files";;
     * ) echo "Action ($Action) is not valid....";;
   esac
}

if [ -f "$1" -o -d "$1" ]
then
   action="action1"
   filelist="$@"
else
   action="$1"
   shift
   filelist="$@"
fi

doAction "$action" "$filelist"  # start function using action and file(s)

exit 0
Quote:
Is getopts a better approach?
Not necessarily better, you stll need to tell getops what is correct and what is not. With a limited amount of options I tend not to use getops (but that is a personal choice).

Hope this helps.
 
Old 03-19-2012, 04:03 AM   #3
dcparris
LQ Newbie
 
Registered: Dec 2011
Location: Charlotte, NC
Distribution: Debian, Kbuntu, CentOS
Posts: 13

Original Poster
Blog Entries: 1

Rep: Reputation: 0
Many Thanks! Shift works. I thought I was not understanding the use of shift, since I could not get action2 to work for the life of me. Through process of elimination, I now realize the problem lay elsewhere (namely inside action2), specifically the file/directory test. But I have learned a lot about hunting bugs - and processing command line arguments.
 
Old 03-19-2012, 10:01 AM   #4
salasi
Senior Member
 
Registered: Jul 2007
Location: Directly above centre of the earth, UK
Distribution: SuSE, plus some hopping
Posts: 4,070

Rep: Reputation: 897Reputation: 897Reputation: 897Reputation: 897Reputation: 897Reputation: 897Reputation: 897
Quote:
Originally Posted by dcparris View Post
Is getopts a better approach?
I never really know, short of actually writing it out both ways (which seems a bit excessive). Getopts can result in cleaner-looking code, if you structure the bit that actually deals with the options well, but 'cleaner' isn't always a synonym for 'better'. The getopts approach hides some of the complexity in getopts out of the way of anyone looking at the script, which feels like an advantage, but unless you understand exactly what getopts does, is it really such an advantage?

I'd have to say that its too close to call, in general, but that you might find that one approach suits your style more than the other.
 
Old 03-19-2012, 10:59 AM   #5
dcparris
LQ Newbie
 
Registered: Dec 2011
Location: Charlotte, NC
Distribution: Debian, Kbuntu, CentOS
Posts: 13

Original Poster
Blog Entries: 1

Rep: Reputation: 0
Thanks for that Salasi, as is frequently true, I suppose it's a matter of there being more than one way to skin a cat.
 
Old 03-19-2012, 11:06 AM   #6
salasi
Senior Member
 
Registered: Jul 2007
Location: Directly above centre of the earth, UK
Distribution: SuSE, plus some hopping
Posts: 4,070

Rep: Reputation: 897Reputation: 897Reputation: 897Reputation: 897Reputation: 897Reputation: 897Reputation: 897
Stupid answer:

http://aplawrence.com/Unix/getopts.html
http://www.shelldorado.com/goodcoding/cmdargs.html
http://www.bash-hackers.org/wiki/dok...topts_tutorial
http://bashcurescancer.com/the-60-se...-tutorial.html
http://stackoverflow.com/questions/4...d-line-options

(It is a stupid answer, because the only thing here is links, and all can be found by the use of a search engine. I still hope that they are valuable, though, because you don't have to sort through all sorts of rubbish to get there.)
 
Old 03-19-2012, 11:06 AM   #7
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
I like getopts because it:
  • is easier to write initially when you have a pro-forma skeleton.
  • deals with no space between the option letters and their arguments.
  • encourages complete error trapping.
  • is easier to extend when the script is further developed.
FWIW here is my pro-forma/boilerplate.
Code:
	lf=$'\n'

	# Set defaults that may be overriden by command line parsing
	# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	# Parse command line
	# ~~~~~~~~~~~~~~~~~~
	emsg=''
	while getopts dhVo: opt 2>/dev/null
	do
		case $opt in
			d )
				debug='YES'
				;;
			h )
				usage -v
				exit 0
				;;
			V )
				echo "$prgnam version $prg_ver"
				exit 0
				;;
			o )
				o_optarg="$OPTARG"
				;;
			* )
				emsg="${lf}Invalid option '$opt'"
		esac
	done

	# Test for extra arguments
	# ~~~~~~~~~~~~~~~~~~~~~~~~
	shift $(( $OPTIND-1 ))
	if [[ $* != '' ]]; then
        	emsg="${lf}Invalid extra argument(s) '$*'"
	fi

	# Test for mandatory options not set
	# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	if [[ ${o_optarg:-} = '' ]]; then
        	emsg="${lf}Mandatory option -o not given"
	fi

	# Report any errors
	# ~~~~~~~~~~~~~~~~~
	if [[ $emsg != '' ]]; then
		echo "$emsg" >&2
        	usage
        	exit 1
	fi

	echo "DEBUG: o_optarg is '$o_optarg'"
 
Old 03-19-2012, 08:00 PM   #8
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Rocky 9.2
Posts: 18,359

Rep: Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751
I agree that if you have varying nums (& types) of params, then getopts is the way to go
 
Old 03-20-2012, 07:07 AM   #9
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,841

Rep: Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308Reputation: 7308
I agree, getopts is a good idea, but it does not support that kind of syntax
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] Bash Script problem running If test on user entered variables Regnets1 Linux - Newbie 3 02-17-2012 02:21 PM
How are arguments passed to a bash script? jiml8 Programming 1 04-09-2009 05:28 PM
bash script arguments R3N3G4D3 Programming 5 11-01-2007 10:16 AM
bash script - variable arguments indikabandara19 Linux - Newbie 4 05-21-2007 10:40 PM
can awk see bash script arguments ? sharapchi Programming 7 12-14-2006 08:03 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Software

All times are GMT -5. The time now is 08:35 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration