Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the advantage of pathmunge over grep?

Currently working on Solaris 10 in the bash shell. While looking at a script, I noticed the pathmunge procedure set up to avoid duplication of folder paths in the PATH (it also seems to have the feature to add the necessary folder at the beginning or the end of the PATH).

Apart from the ability to append/pre-pend (pardon if that is the wrong term) to the PATH, why cannot we simply do an echo ${PATH} | grep <folder one wishes to add> ?

If my only intent is to have a certain folder in the PATH (and not really concerned about the beginning or end), would a grep serve the purpose?

like image 472
Parag Doke Avatar asked Feb 16 '11 05:02

Parag Doke


People also ask

What is Pathmunge?

pathmunge is a shell function to add a directory to the PATH.

What is bash $@?

bash [filename] runs the commands saved in a file. $@ refers to all of a shell script's command-line arguments. $1 , $2 , etc., refer to the first command-line argument, the second command-line argument, etc. Place variables in quotes if the values might have spaces in them.


2 Answers

Until 2012, pathmunge used to use grep itself. (Well, egrep, to be precise.)

In Red Hat, CentOS, etc. pathmunge is defined in /etc/profile:

pathmunge () {
        if ! echo $PATH | /bin/egrep -q "(^|:)$1($|:)" ; then
           if [ "$2" = "after" ] ; then
              PATH=$PATH:$1
           else
              PATH=$1:$PATH
           fi
        fi
}

As you can see, it's slightly more sophisticated than what you propose to do, but not much. The reason your proposal wouldn't work is that without the delimiters it'll make partial matches.

so if my path is /usr/local/sbin:/usr/local/bin, echo ${PATH} | grep /usr/local will return true, even though /usr/local isn't in my path. So you need to match the delimiters. But if you grep for :/usr/local: you'll also fail, because you won't ever match the first or last item in the path, since $PATH neither starts nor ends with delimiter. That's why egrep is used. (^|:) matches either a colon or the beginning of the line. ($|:) matches either a colon or the end of the line.

Modern versions of pathmunge use the shell's built-in pattern-matching capabilities, which is a little more efficient.

like image 97
Ori Avatar answered Nov 15 '22 18:11

Ori


I propose an evolution to pathmunge, which I use for 2 years now.

pathmunge() {
if [ -d "$1" ]; then
  realpath / 2>&1 >/dev/null && path=$(realpath "$1") || path="$1"
  # GNU bash, version 2.02.0(1)-release (sparc-sun-solaris2.6) ==> TOTAL incompatibility with [[ test ]]
  [ -z "$PATH" ] && export PATH="$path:/bin:/usr/bin"
  # SunOS 5.6 ==> (e)grep option "-q" not implemented !
  /bin/echo "$PATH" | /bin/egrep -s "(^|:)$path($|:)" >/dev/null || {
    [ "$2" == "after" ] && export PATH="$PATH:$path" || export PATH="$path:$PATH"
  }
fi
}

1) It checks for validity of the directory, for a minimal performance cost

2) It uses realpath as well, and the command realpath is tested as well. realpath your paths before adding it to $PATH

3) egrep -q is unavailable on SunOS 5.6 (yes it is still in use in many companies)

like image 22
scavenger Avatar answered Nov 15 '22 17:11

scavenger