2012-07-11 18 views
6

Ben Say uyarıyı üretyolunda birden çok yürütülebilir bash komutunu çalıştırarak

Bu işlevsellik gerçekten gerçekten bir sürü zaman bugün beni kurtardı olurdu
>foo 
Warning: multiple foo in PATH 
... foo gets executed ... 

. Bunun daha erken olduğunu tahmin etmeliydim ama sorun bana başlangıçta belirsizdi ve tam tersi olarak kazmaya başladım.

cevap

6

Eh, bunu yapabilirsiniz, ancak düşündüğünüzden kadar kolay değildir: istenilen sonucu elde etmek için yerine DEBUG tuzağı kullanın. İlk olarak, PATH'daki tüm dizinleri denetleyecek bir işlev oluşturmanız ve çalışmaya çalıştığınız komut için oraya bakmanız gerekir. Ardından bu işlevi geçerli kabuğunuzun DEBUG tuzağına bağlamanız gerekir. kullanım

$ 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 

Örnek:

Bunu yapan bir küçük senaryo yazdı, PROMPT_COMMAND burada yardımcı olmaz bildiğim kadarıyla anlayabileceği şekilde

$ . /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 
$ 
+2

"$ PATH" üzerinde yineleme yerine, 'type -pa" $ 1 "' yi kullanabilirsiniz. Ayrıca 'history''i ayrıştırmak yerine' $ BASH_COMMAND' kullanabilirsiniz. 'Preexec' işlevi başka bir bağlamda bir amaca hizmet etmelidir, ancak buradaki yabancıdır. –

+0

Ohh, soruya verilen cevaplarda e-posta ile bilgilendirileceğini düşündüm. ** Teşekkürler. ** Sanırım diğer şeyler daha bariz bash mashinery olduğu gibi kısa cevap "DEBUG tuzak kullanın" olacaktır. Bu bakımdan cevabın ve @lynxlynxlynx birinin de iyi biri. Yine de, sizinki gibi cevaplarınızı sadece en üstte, başka hiçbir sebepten dolayı oylamıyorum. – nshy

2

Bu, genelleme için biraz hile olsa da mümkündür. Cevabımı history ve PROMPT_COMMAND sihirbazı için https://unix.stackexchange.com/q/42579/20437'a bakın. Sizin checkSanity işlevi aşağıdaki gibi görünecektir:

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 
} 

Ama bu değil başında, komut tamamlandıktan sonra uyarı yazdırılır.

trap 'checkSanity "$BASH_COMMAND"' DEBUG 
+1

; komut satırına girmeden önce, sonra değil yürütülür. –

+0

çalışır, ancak komut bittikten sonra uyarı alırsınız. DEBUG tuzağı bu açıdan çok yönlüdür. – lynxlynxlynx

+0

bu rigt; ve tarih ile bu fikir -a da o kadar iyi değildir, çünkü yan etkileri vardır; Her zaman tarihini saklamak istemezsin. neden sadece tarih çıkışını kontrol etmek istemiyorsun? –

İlgili konular