回答:
一部のシステムで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 -a
zshの下であなたが望むことをします:
7:27AM 7 % whence -a cat
/usr/bin/cat
/bin/cat
/usr/bin/cat
/bin/cat
zshでPATHをクリーンアップする必要がありますが、重複がたくさんあります。whence -a
kshでは異なる動作をします:
$ whence -a cat
cat is a tracked alias for /usr/bin/cat
私も言わなければならない、それは潜在的に有用な動作のようです。
which --all
。