说我有:
>which -a foo
/bin/foo
/usr/bin/foo
我想要类似的东西:
>foo
Warning: multiple foo in PATH
... foo gets executed ...
这个功能今天真的让我节省了很多时间。 我应该猜到这种情况发生得比较早,但问题还不清楚 在开始的时候,我开始向相反的方向挖掘。
答案 0 :(得分:6)
嗯,你可以做到,但这并不像你想象的那么容易。
首先,您需要创建一个将要检查的函数 PATH中的所有目录,并查看您尝试运行的命令。 然后,您需要将此函数绑定到当前shell的DEBUG陷阱。
我写了一个小脚本来做到这一点:
$ 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
使用示例:
$ . /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
$
答案 1 :(得分:2)
虽然有点技巧可以推广,但这是可能的。请参阅https://unix.stackexchange.com/q/42579/20437对history
和PROMPT_COMMAND
魔法的回答。你的checkSanity函数看起来像这样:
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
}
但是,这将在命令完成后打印警告,而不是在开始时。使用DEBUG陷阱来获得想要的结果:
trap 'checkSanity "$BASH_COMMAND"' DEBUG