「command_not_found_handle」をローカルでオーバーライドする方法は?

「command_not_found_handle」をローカルでオーバーライドする方法は?

一般的に、おなじみの command_not_found 動作をグローバルに維持しながらコマンドが見つからない場合、特定の bash スクリプトが迅速に失敗するようにしたいと思います。たとえば、次をに保存すると/tmp/foo.sh...

# ----------------------------start foo.sh----------------------------
THIS_FP="$0"
THIS_FN="$(basename ${THIS_FP})"
THIS_DIR="$(dirname ${THIS_FP})"

function setup {
  for CMD in \
    'foo' \
  ; do
    echo -e "\n$ ${THIS_FN}::${FUNCNAME[0]}::${CMD}"
    eval "${CMD}"
  done
} # end function setup

function teardown {
  for CMD in \
    "ls -alt ${THIS_DIR} | head" \
  ; do
    echo -e "\n$ ${THIS_FN}::${FUNCNAME[0]}::${CMD}"
    eval "${CMD}"
  done
} # end function teardown

for CMD in \
  'setup' \
  'teardown' \
; do
  echo -e "\n$ ${THIS_FN}::main loop::${CMD}"
  eval "${CMD}"
done
# ------------------------------end foo.sh----------------------------

...実行可能にしてから実行すると取得できます。

# ----------------------------not what I want-------------------------
me@it:~$ /tmp/foo.sh 

$ foo.sh::main loop::setup

$ foo.sh::setup::foo
/tmp/foo.sh: line 10: foo: command not found

$ foo.sh::main loop::teardown

$ foo.sh::teardown::ls -alt /tmp | head
total 68840
drwxrwxrwt 22 root  root           1600 May  6 18:49 .
-rwxr-xr-x  1 me    me         527 May  6 18:49 foo.sh
drwx------  2 me    me          40 May  6 17:54 plugtmp-1
srw-------  1 me    me           0 May  6 17:28 tramp.13004aZf
drwx------  2 me    me        4200 May  6 17:22 matecorba-me
drwx------  2 me    me          40 May  6 02:20 plugtmp
-rw-------  1 me    me     2034335 May  4 14:21 s_TTRuhW.mp3.part
-rw-------  1 me    me     1658381 May  2 12:21 +rM4IttD.mp3.part
-rw-r--r--  1 me    me       86420 May  1 19:22 duplicity_20130501_1917.txt
# ----------------------------not what I want-------------------------

代わりに私がしたいことこのスクリプトのみfoo.sh失敗し、「コマンドが見つかりません」が発生するとすぐに失敗します。

# ------------------------------what I want---------------------------
me@it:~$ /tmp/foo.sh 

$ foo.sh::main loop::setup

$ foo.sh::setup::foo
/tmp/foo.sh: ERROR: foo: command not found

# Throwing me back to the shell from which I invoked foo.sh,
# *without* changing the usual friendly behavior outside it, e.g.:

me@it:~$ foo
No command 'foo' found, did you mean:
 Command 'fio' from package 'fio' (main)
 Command 'xoo' from package 'xoo' (main)
 Command 'fop' from package 'fop' (main)
 Command 'fox' from package 'objcryst-fox' (main)
 Command 'zoo' from package 'zoo' (main)
 Command 'goo' from package 'goo' (main)
foo: command not found
# ------------------------------what I want---------------------------

編集でこの動作を提供できますか?ただ foo.sh.bashrc、または現在インストールされている他のファイルに触れていませんか?それでは、どうすればいいですか?そうでなければなぜならないのですか?

ベストアンサー1

エラーが発生した直後にスクリプトを終了するには、次のコマンドを使用してスクリプトを実行するか、スクリプトの先頭にbash -e /tmp/foo.sh次の行を入力しますset -e

-eあるいは、errexit「エラー」が発生した場合は、すぐにスクリプトを終了するようにbashに指示してください。この方法はerrexitそれより少し複雑であり、常に期待どおりに機能するわけではありません。詳細については、次の記事を読んでください。http://mywiki.wooledge.org/BashFAQ/105(「なぜ-eを設定(または-o errexitまたはトラップERRを設定)した場合、期待どおりに機能しないのですか?))

bashスクリプトでは、「コマンドが見つかりません」処理は(通常は)有効になりません。これは、bashスクリプトがbashrcを読み取らずcommand_not_found_handle(通常)いくつかのbashrc(debianなど/etc/bash.bashrc)で定義されているためです。

コマンドが見つかりません処理がスクリプトで無効になっていることを確認するには、次のように関数定義を無効にします。

if [ x"$(type -t command_not_found_handle)" = x"function" ]; then
    unset -f command_not_found_handle
fi

bashスクリプトでこれを行うと実装する代わりにスクリプト購入command_not_found_handlebashスクリプトでのみ定義されていません。対話型シェルの状態は、command_not_found_handleスクリプトが実行される前の状態のままです。

詳細については、次の記事を読んでください。https://superuser.com/questions/176783/what-is-the-difference-Between-executing-a-bash-script-vs-commerce-it

その間、次の内容evalも読んでください。http://mywiki.wooledge.org/BashFAQ/048(「評価コマンドとセキュリティの問題」)

おすすめ記事