私が持っているとしましょう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/bin
foo
echo ":${PATH}:"
$PATH
sed
: $this_dir :
("clear"のためのスペースを追加して)次に置き換えます。
:
つまり、$this_dir
から削除されます":${PATH}:"
。その後、前と後のコロンを削除します。
PATH
次に一時的にに設定し、$redacted_PATH
usefoo
を検索しますwhich
。成功すると、実行に使用した実際の(公開/共有/システム)コピーへのフルパス(たとえば、/bin/foo
または)が得られます。一時的に変更するだけなので、ユーザーエクスペリエンスにアクセスできるので、実行すると存在する場合に見つけることができます。/usr/bin/foo
foo
PATH
/bin/foo
$PATH
/bin/foo
brillig
$HOME/bin/brillig
$HOME/bin
何度も発生すると問題が発生する可能性がありますが、$PATH
修正することは難しくありません。