Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate warning when multiple executables in path when executing command in bash

Tags:

bash

Say I have:

>which -a foo
/bin/foo
/usr/bin/foo

I want something like:

>foo
Warning: multiple foo in PATH
... foo gets executed ...

This functionality would have saved me really really lots of time today. I should have guessed this is happening earlier but the problem was unclear to me at the beggining and I started to dig in quite opposite direction.

like image 247
nshy Avatar asked Jul 11 '12 12:07

nshy


2 Answers

Well, you can do it, but it is not so easy as you may think.

First, you need to create a function that will check all directories in the PATH, and look there for the command you try to run. Then you need to bind this function to the DEBUG trap of your current shell.

I wrote a small script that does that:

$ cat /tmp/1.sh

check_command()
{
    n=0
    DIRS=""
    for i in $(echo $PATH| tr : " ")
    do 
        if [ -x "$i/$1" ]
        then 
            n=$[n+1]
            DIRS="$DIRS $i"
        fi
    done
    if [ "$n" -gt 1 ]
    then
      echo "Warning: there are multiple commands in different PATH directories: "$DIRS
    fi
}

preexec () {
    check_command $1
}
preexec_invoke_exec () {
    [ -n "$COMP_LINE" ] && return  # do nothing if completing
    local this_command=`history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//g"`;
    preexec "$this_command"
}
trap 'preexec_invoke_exec' DEBUG

Example of usage:

$ . /tmp/1.sh
$ sudo cp /bin/date /usr/bin/test_it
$ sudo cp /bin/date /bin/test_it
$ test_it
Warning: there are multiple commands in different PATH directories:  /usr/bin /bin
Wed Jul 11 15:14:43 CEST 2012
$ 
like image 65
Igor Chubin Avatar answered Nov 09 '22 22:11

Igor Chubin


It is possible, though a bit trick to generalise. See my answer to https://unix.stackexchange.com/q/42579/20437 for the history and PROMPT_COMMAND magic. Your checkSanity function would look something like this:

checkSanity() {
  cmd="${1%% *}" # strip everything but the first word
  candidates=$(which -a $cmd | wc -l)
  if (( candidates > 1 )); then
    echo "Warning: multiple $cmd in PATH"
  fi
}

But that will print the warning after the command finishes, not at the start. Use the DEBUG trap instead to get the wanted result:

trap 'checkSanity "$BASH_COMMAND"' DEBUG
like image 28
lynxlynxlynx Avatar answered Nov 10 '22 00:11

lynxlynxlynx