Bash function failing with [: too many arguments


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Bash function failing with [: too many arguments
# 1  
Old 10-10-2017
Bash function failing with [: too many arguments

I'm reading Wicked Cool Shell Scripts. For some reason, the function pasted in below gives the error: ./inpath2: line 10: [: too many arguments. What am I missing?





Code:
in_path()
  4 {
  5 cmd=$1     ourpath=$2    result=1
  6 oldIFS=$IFS   IFS=":"
  7 
  8 for directory in "$ourpath"
  9 do
 10   if [ -x $directory/$cmd ] ; then
 11     result=0
 12   fi
 13   done
 14 
 15   IFS=$oldIFS
 16   return $result
 17 
 18 }


Last edited by Scott; 10-10-2017 at 08:41 AM.. Reason: Replaced ICODE with CODE tags
# 2  
Old 10-10-2017
Are there spaces in any of the $directory ($ourpath) or arguments to the script ($cmd)?

It's always a good idea to double-quote variables, including when they're passed to the function. for works on words, so if there are spaces around it will iterate once for each word in the string.
This User Gave Thanks to Scott For This Post:
# 3  
Old 10-10-2017
There's not supposed to be spaces. The script is meant to find and determine if a file is executable based on the user's path. The idea is that it can deal with "ls" or "/bin/ls."
# 4  
Old 10-10-2017
The first thing I would usually do here is echo the variables before the test (before the if), and do some sanitation on them. I would also declare each variable on its own line, and quote them when using them.
# 5  
Old 10-10-2017
Quote:
Originally Posted by jakeroberts
I'm reading Wicked Cool Shell Scripts. For some reason, the function pasted in below gives the error: ./inpath2: line 10: [: too many arguments. What am I missing?





Code:
in_path()
  4 {
  5 cmd=$1     ourpath=$2    result=1
  6 oldIFS=$IFS   IFS=":"
  7 
  8 for directory in "$ourpath"
  9 do
 10   if [ -x $directory/$cmd ] ; then
 11     result=0
 12   fi
 13   done
 14 
 15   IFS=$oldIFS
 16   return $result
 17 
 18 }

To be honest i don't see how this is supposed to be "cool". "Wicked" yes, but cool?

I'd write it this way and you will understand why once you have scripts several thousand lines long to maintain. If this is meant for bash instead of ksh replace "typeset" with "local":

Code:
in_path()
{
typeset    chCmd="$1"                # command
typeset    fOurPath="$2"             # list of colon-separated dirs
typeset    fDir=""                   # single directory buffer

$chFullDebug

echo "$fOurPath" |\
while IFS=":" read fDir ; do
     if [ -x "${fDir}/${chCmd}" ] ; then
          return 0
     fi
done

return 1
}

A few things to notice:

Variables can change their content easily in shell scripts. Strings can become numbers and vice versa. To maintain a modicum of runtime security i always use qualifiers (see "Hungarian Style Notation") to denote the "type" of a variable. This helps me to keep track in complicated and long scripts. I use:

f... = "file", a filename, directory or generally a path
i... = "int", an integer number
ch.. = "char", a string
l... = "logical", basically an int, but i use only values 0 and 1

It doesn't matter what system you use as long as you stay consistently with it. You do not need to adopt my system, but you should have some system, otherwise you will create a mess over time.

Second: i have declared all my variables i use in the function. This not only encapsulates the function (there is no danger with side effects) but i can also document what i use the variables for and what they should contain. If something goes wrong i can display what is in the variables and compare that with the the mini-data-dictionary at the top of the function.

Third: when the test for an executable is positive there is no point in testing the rest of the path. Therefore i leave the loop immediately via the return-statement in this case.

Fourth: using the while-loop i can specify a custom IFS for the single read-command, so i do not need to save and restore the IFS.

Fifth: all the strings are protected by double-quotes always. This increases run-time security because this way i never have to worry about strings containing white space.

And finally: you notice the line $chFullDebug. This variable is nowhere defined or used in the function. It is a global which i set in my scripts. Under normal conditions the variable is an empty string and the line does nothing. If i need to fully debug a script i set this to set -xv because setting these shell options in the main program would have them switched off with every entering of a subfunction. This way, by writing it into every function i can globally switch debugging on or off.

I hope this helps.

bakunin

Last edited by bakunin; 10-10-2017 at 02:38 PM..
# 6  
Old 10-10-2017
Quote:
Originally Posted by Scott
The first thing I would usually do here is echo the variables before the test (before the if), and do some sanitation on them. I would also declare each variable on its own line, and quote them when using them.
Thanks for the quick replies. I'm at work now, but I will try this when I get home. Thanks again.
# 7  
Old 10-10-2017
Wrong quoting.
The for loop actually needs to split on IFS that is set to : so $ourpath must not be in quotes.
The arguments in the following [ ] test should be quoted in general.
Code:
  8 for directory in $ourpath
  9 do
 10   if [ -x "$directory/$cmd" ] ; then

Not quoting the $ourpath bares a risk with special characters.
However, a IFS=: read line has the problem that the full line is read into line; splitting would take place with FS=: read field1 field2 but then you must know the number of fields, so you would need to split into an array, but arrays are a bit specific to bash or ksh...
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Call same function using 2 different arguments

I have a script that uses 2 arguments. I want to call the function part within this script using these same arguments. Below is what I came up with below script so far, any guidance would be helpful. Thank you! cat backup.sh #!/bin/bash function usage { echo "USAGE: $(basename $0)... (6 Replies)
Discussion started by: mbak
6 Replies

2. Shell Programming and Scripting

Bash Regexp failing: unexpected token `('

Hey guys, I'm fairly new to bash scripting, so bear with me :) What I want to achieve is reading a file (.php), find the phrase 'WACHTWOORD' (password) in it, and collect the password and a part of the filename in a list. The filename is always 'settings_{name}.php' and the part I'm looking... (6 Replies)
Discussion started by: Eggie01
6 Replies

3. UNIX for Dummies Questions & Answers

Invoke Function WithOut Non-Positional Arguments

Hello Everyone, Is there a way i can pass the arguments as parameters or variables instead of positional arguments to a function, below i am calling the function defined in a script. Call: notify "Error While Generating The List File: ${GEN_PARAM_LIST9} For Feed Data Validation Errors In... (1 Reply)
Discussion started by: Ariean
1 Replies

4. Shell Programming and Scripting

Need to call a function with arguments

I need to call a function within a code with $database and $ service as the arguments How do I proceed ? and how would a function be defined and these two arguments would be used inside the function? calc_pref_avail $database $service Best regards, Vishal (7 Replies)
Discussion started by: Vishal_dba
7 Replies

5. Shell Programming and Scripting

bash read within function with arguments

I have trouble getting this logic to work #!/bin/bash function assign_var(){ while do read -p "$2 :" $3 done } assign_var '$IPADDRESS' ipaddress IPADDRESS Basicly, i want to make sure that entry is made (i can add more sophisticated checks later), but the idea is to recycle... (11 Replies)
Discussion started by: serverchief
11 Replies

6. UNIX for Advanced & Expert Users

Function not called when no arguments is passed

Hi Guys, I am trying to pass arguments to the script i am wrinting. When no argument is passed or wrong argument is passed, the script needs to output the way it needs to be called and exit. Currently, when no arguments is passed, it is not getting exited but goes on assuming those... (3 Replies)
Discussion started by: mac4rfree
3 Replies

7. Shell Programming and Scripting

cat arguments to a function

Hi, I've a logging function in bourne shell, flog() which logs the first argument passed to it. How can I pass arguments to this function from a file, like cat filename | sed '...filtering...' | flog or cat filename | sed '...filtering...' | xargs flog Which did not work, after which... (3 Replies)
Discussion started by: Random_Net
3 Replies

8. Programming

Error: too many arguments to function 'sigwait'

#include <pthread.h> #include <signal.h> ... sigset_t mask; int err,signo; err=sigwait(&mask,&signo); switch(signo){ case SIGINT: ... } when I compile above code under solaris 10,it raise following error: error: too many arguments to function 'sigwait' I look up signal... (4 Replies)
Discussion started by: konvalo
4 Replies

9. Shell Programming and Scripting

no of arguments to function in shell script

Hi, I have a function in shell script fun1{ echo "No.of arguments are..."} this function will be called in same script by passing arguments fun 1 2 3 I want to check the no. of arguments passed to fun1 function in the same functionbefore validation. can any one suggest me. (2 Replies)
Discussion started by: KiranKumarKarre
2 Replies

10. Programming

sscanf function is failing

Please delete this thread. (0 Replies)
Discussion started by: jxh461
0 Replies
Login or Register to Ask a Question