回答:
一部のシステムでwhich -aは、すべての一致を表示します。シェルがbashまたはzsh¹の場合は、type代わりに使用できます。type foo最初の一致をtype -a foo表示し、すべての一致を表示します。3つのコマンドtype、whichおよびwhenceはほぼ同じことを行います。シェルとオペレーティングシステムでは、可用性、オプション、およびそれらが正確に報告する内容が異なります。typeは常に使用可能であり、コマンドのような名前(エイリアス、キーワード、シェル組み込みコマンド、関数、外部コマンド)をすべて表示します。
すべての一致を表示する完全に移植可能な唯一の方法は、$PATH自分自身を解析することです。これを行うシェルスクリプトを次に示します。シェル関数にする場合は、関数本体を括弧で囲み(関数が変更さIFSれset -fてエスケープされないように)、に変更exitしてくださいreturn。
#!/bin/sh
set -f # disable globbing
IFS=: # break words at : only
not_found=1
for d in $PATH; do
if [ -f "$d/$x" ] && [ -x "$d/$x" ]; then
printf '%s\n' "$d/$x"
not_found=0
fi
done
exit $not_found
¹ または、ドキュメントによるとksh 93ですが、ksh 93s + 2008-01-31は最初に一致したものだけを印刷しようとします。
sh空のコンポーネントがある場合、そのコードは正しく機能しません$PATH。また$IFS、フィールド区切り文字であることに注意してください(少なくともPOSIXシェルでは)。$PATHコロンはフィールド区切り文字として使用されます。which正しい実装については、Debianにあるスクリプトをご覧ください。
type組み込みがksh93u+ 2012-08-01正常に動作するようです。
--allフラグまたは-aフラグは、パス内のすべての一致とエイリアスを表示します(少なくともFedora、Ubuntu、およびCentOSでは):
which -a which
AIXおよびSolarisの場合、これにより次のようになります。
echo "$PATH" | sed -e 's/:/ /g' | \
while read -r p; do find "$p" -type f -name "which"; done
$PATH空白文字やシェルグロビング文字が含まれているとスクリプトが機能しません。read -rバックスラッシュに対処するために必要です。find時間がかかり、$PATHディレクトリにサブディレクトリが含まれる場合、誤った一致を返す可能性があるため、これは良い方法ではありません。幸いなことに、findここでは役に立ちません。私の答えをご覧ください。
whichサポートしていない-a、またはwhence利用できない場合は、独自にロールしてください:
#!/bin/sh -f
IFS=":"
for PART in $PATH
do
if test -x "$PART/$1"
then
echo $PART/$1
fi
done
set -f保護されていない上グロブオフにします$PATH。test -fここでは実行可能ファイルのみが必要なので、十分ではありません。あなたが必要test -xです。うーん、スクリプトで通常のファイルテストを忘れていたことがわかりました。
whence README.txtそうではないと思いますwhence "file* wi?h we!rd name"。横断するのがどれほど簡単かを示すだけ$PATHです。
kshとzshには、シェルとして「whence」が組み込まれています。 whence -azshの下であなたが望むことをします:
7:27AM 7 % whence -a cat
/usr/bin/cat
/bin/cat
/usr/bin/cat
/bin/cat
zshでPATHをクリーンアップする必要がありますが、重複がたくさんあります。whence -akshでは異なる動作をします:
$ whence -a cat
cat is a tracked alias for /usr/bin/cat
私も言わなければならない、それは潜在的に有用な動作のようです。
which --all。