Bashで隠されたプログラムをどのように見つけることができますか?

Bashで隠されたプログラムをどのように見つけることができますか?

私が持っているとしましょうPATH="home/bob/bin:/usr/bin"。私は/home/bob/bin/fooいくつかの修正を/usr/bin/foo行った後。実際、実際のfooは複数の場所にある可能性があるので、PATHで探したいと思います。私の新しいfooスクリプトも私のパスにあるので、fooを呼び出すことはできず、これは再帰呼び出しを引き起こします。

Bashスクリプトでこれを行う簡単な方法はありますか? (PATH要素を繰り返して手動で検索する以外に?)

答え1

以下を使用すると、いつでも2番目のパスを取得できますfoo

foo=$(type -Pa foo | tail -n+2 | head -n1)

(ファイルパスに改行文字が含まれていない場合)

これは相対パスであり、実行後は無効になりますcd

これにより、次のことができます。

hash -p "$foo" foo

だからそれ foo実行時に呼び出されますfoo

答え2

列挙よりも良いことはないと思いますPATH。それほど難しくありません。

#!/bin/bash
set -f; IFS=:
for d in $PATH; do
  if [[ -f $d/foo && -x $d/foo && ! $d/foo -ef /home/bob/bin/foo ]]; then
    exec "$d/foo" "$@"
    exit 126
  fi
done
echo "$0: foo (real) not found in PATH"
exit 127

PATHに空のエントリがないとします。空のPATHエントリは有害です。.明示的に作成してください(またはまったく含めない方が良い)。

他のプログラムではなくコマンドラインでのみ実行する場合は、スクリプトではなく関数fooとして作成してください。関数内でcommand foo関数を非表示にするには、実行してください。

答え3

fooが重要な場合は、スクリプトで設定する必要があります。スクリプトに明示的にリンクできるので、これは良い習慣だと思います。私は間接的、暗黙的、または隠されたものが好きではありません。スクリプトをデプロイするには非常に単純でなければなりません。

そうでなければ必ず見つけなければならないなら、探す方法は次のとおりです。

whereisfoo="$(which foo)"

それが十分でない場合、あなたがやっていることは複雑すぎるようです。

答え4

私はこれがGilesの答えより少し混乱しやすいアプローチだと思います(これは主観的な判断であることを認めますが)。

#!/bin/sh
this_dir=$(dirname "$0") # または this_dir=$HOME/bin でハードコードすることもできます。
redacted_PATH=$(echo ":${PATH}:" | sed -e "s:\:$this_dir\::\::" -e "s/^://" -e 's/:$// ')
if obliged_prog=$(PATH=$redacted_PATH which foo)
それから
            ⋮ # /usr/bin/foo を実行する前にすべきこと
        "$(obscured_prog)"議論          #"$@" であってもなくてもよい。
            ⋮ # /usr/bin/foo を実行した後にすべきこと
その他
        echo "$0: PATH に foo (間違い) が見つかりません。"
            ⋮#必要なすべてのコード。
フィリピン諸島

これは、このプライベートコピーを含むディレクトリを除いてredacted_PATH設定されます。の先頭と末尾にコロンを追加すると、各コンポーネントの前後にコロンが続きます。最初と最後のコンポーネントも同様です。検索回数は$PATH$HOME/binfooecho ":${PATH}:"$PATHsed

: $this_dir :

("clear"のためのスペースを追加して)次に置き換えます。

:

つまり、$this_dirから削除されます":${PATH}:"。その後、前と後のコロンを削除します。

PATH次に一時的にに設定し、$redacted_PATH usefooを検索しますwhich。成功すると、実行に使用した実際の(公開/共有/システム)コピーへのフルパス(たとえば、/bin/fooまたは)が得られます。一時的に変更するだけなので、ユーザーエクスペリエンスにアクセスできるので、実行すると存在する場合に見つけることができます。/usr/bin/foofooPATH/bin/foo$PATH/bin/foobrillig$HOME/bin/brillig

$HOME/bin何度も発生すると問題が発生する可能性がありますが、$PATH修正することは難しくありません。

関連情報