LinuxQuestions.org
Latest LQ Deal: Complete CCNA, CCNP & Red Hat Certification Training Bundle
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 02-23-2013, 03:53 PM   #1
moraxu
LQ Newbie
 
Registered: Dec 2012
Distribution: Ubuntu
Posts: 15

Rep: Reputation: Disabled
Searching a colon-separated list of directories


Hello,

I was given this exercise:

Quote:
Write a function named funload that takes as its single argument the name of a file containing other functions. The purpose of funload is to make all functions in the named file available in the current shell; that is, funload loads the functions from the named file. To locate the file, funload searches the colon-separated list of directories given by the environment variable FUNPATH. Assume that the format of FUNPATH is the same as PATH and that searching FUNPATH is similar to the shell’s search of the PATH variable.
Below is my function. Do you have any remarks regarding it? Does something can be simplified?

Code:
function funload()
{
	if [ $# -ne 1 ]
	then
		echo "Invalid arguments!" 1>&2
		echo "Usage: funload simple_filename" 1>&2
		return 1
	fi

	if [ -z "$1" ]
	then
		echo "Filename is an empty string!" 1>&2
		echo "Usage: funload simple_filename" 1>&2
		return 1
	fi
	
	if [ $(basename "$1") != "$1" ]
	then
		echo "Filename isn't a simple filename!" 1>&2
		echo "Usage: funload simple_filename" 1>&2
		return 1
	fi
	
	if [[ -z "$FUNPATH" || "$FUNPATH" =~ ^\ +$ ]]
	then
		echo "Environment variable FUNPATH is unset or empty!" 1>&2
		return 1
	fi

	# After tests, I assume that every pathname
	# in the variable is an absolute pathname
	
	local current_path all_paths=$FUNPATH prev_all_paths

	while [ "$all_paths" != "$prev_all_paths" ]
	do
		current_path=${all_paths%%:*}

		if [ -z "$current_path" ]
		then
			[ -e ~/"$1" ] && { . ~/"$1" ; return ; }
		else
			[ -e "$current_path/$1" ] && { . "$current_path/$1" ; return ; }
		fi
		
		prev_all_paths=$all_paths
		all_paths=${all_paths#*:}
		
		if [ -z "$all_paths" ]
		then
			[ -e ~/"$1" ] && { . ~/"$1" ; return ; }
		fi
		
	done
}

Last edited by moraxu; 02-23-2013 at 04:13 PM.
 
Old 02-23-2013, 04:29 PM   #2
rigor
Member
 
Registered: Sep 2011
Posts: 254

Rep: Reputation: Disabled
Whether or not these suggestions are appropriate to your situation can naturally depend on what limitations your instructor may impose.

I would tend to have a single return code for success, but different return codes for different failures. That's so the calling program can determine the nature of the failure, if it needs to do so.

If I'm going to output a fixed message, in which I don't want any substitutions, I would tend to use single quotes ( with proper adjustments for any included "apostrophes" ).

If the usage message is always the same, rather than repeat the same code again and again, to output the usage message, I'd be prone to make a usage() function, then call the usage() function. Or in this case, since it appears to be that funload() might be a function that is to be made available directly in the shell's environment, I'd probably name the usage() function something like funload_usage().

Although it may not be a great idea from the standpoint of security, strictly speaking, the PATH can contain relative path's, such as "dot". So I might not assume that each "pathname" is absolute, if you are meant to process FUNPATH as the shell would process PATH.
 
1 members found this post helpful.
Old 02-24-2013, 08:53 PM   #3
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian + kde 4 / 5
Posts: 6,834

Rep: Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976
Just to be clear, is this a bash script, a POSIX-compliant sh script, or something else? The syntax you're using appears to be bash.


1) POSIX function declaration syntax is "funcname()". In bash you can also use "function funcname". Use one or the other, not both. Although bash won't complain if you do, other shells may not be so nice.

2) If possible, I would instead first split the FUNPATH into an array. Then you can simply use a for loop to iterate over the entries for the search. Use a break command to exit the loop when/if a match is found.

3) Instead of multiple separate if statements, you should probably combine them into a single if..elif..else.

4) basename can be replaced with a simple parameter substitution. ( "${path##*/}" )

5) Finally, be consistent. If the shell supports "[[..]]", then use that exclusively. Except also that in bash/ksh, numeric comparisons should be done with "((..))" instead.

http://mywiki.wooledge.org/BashFAQ/031
http://mywiki.wooledge.org/ArithmeticExpression
 
1 members found this post helpful.
Old 02-25-2013, 11:42 AM   #4
moraxu
LQ Newbie
 
Registered: Dec 2012
Distribution: Ubuntu
Posts: 15

Original Poster
Rep: Reputation: Disabled
OK, thanks for answers. Yes, it's a bash script.

Quote:
Originally Posted by David the H. View Post
If possible, I would instead first split the FUNPATH into an array. Then you can simply use a for loop to iterate over the entries for the search. Use a break command to exit the loop when/if a match is found.
I was going to do so, but after considering that pathname might contain a whitespace, dropped this idea.
 
Old 02-25-2013, 12:26 PM   #5
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 9,550

Rep: Reputation: 2898Reputation: 2898Reputation: 2898Reputation: 2898Reputation: 2898Reputation: 2898Reputation: 2898Reputation: 2898Reputation: 2898Reputation: 2898Reputation: 2898
Quote:
I was going to do so, but after considering that pathname might contain a whitespace, dropped this idea.
This need only be a concern if not dealt with. Try considering what determines how an array is built and look at how you might change the necessary delimiter to your needs.
 
Old 02-26-2013, 08:05 AM   #6
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian + kde 4 / 5
Posts: 6,834

Rep: Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976
Indeed. The possibility of encountering whitespace is one of the best reasons why you should use arrays for lists of things. The only question comes in loading it properly in the first place.

You'll find the answer to that in these two links:

How can I use array variables?
http://mywiki.wooledge.org/BashFAQ/005/

How do I do string manipulations in bash?
http://mywiki.wooledge.org/BashFAQ/100
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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] splitting of comma separated values file (horizontal) into a list (vertical ) list Donoughue Linux - Newbie 3 10-20-2011 02:18 PM
sorting a list into comma separated list nixlearn Linux - Newbie 22 12-03-2008 07:21 AM
Need help searching through a list of directories Twilight Linux - Newbie 5 02-21-2008 10:02 AM
Removing a colon and all characters before it, in a python list tangle Programming 4 09-12-2006 10:48 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 07:40 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
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration