「これ」、しかしすべて


19

ほとんどの人がwhichコマンドに精通していると思うので、頻繁に使用しています。私はちょうど、どのコマンドが私のパスの最初であるかだけでなく、すべてのパスのすべてのコマンドがいくつで、どこにあるのか興味があります。which manページを試してみましたが(入力するman whichと笑いました)、何も表示されませんでした。


1
私のシステムでは、manページに最初にリストされていますwhich --all
ショーンJ.ゴフ

2
私の場合(Linux)のみwhich -aです。
ユーザー不明

回答:


23

一部のシステムでwhich -aは、すべての一致を表示します。シェルがbashまたはzsh¹の場合は、type代わりに使用できます。type foo最初の一致をtype -a foo表示し、すべての一致を表示します。3つのコマンドtypewhichおよびwhenceはほぼ同じことを行います。シェルとオペレーティングシステムでは、可用性、オプション、およびそれらが正確に報告する内容が異なります。typeは常に使用可能であり、コマンドのような名前(エイリアス、キーワード、シェル組み込みコマンド、関数、外部コマンド)をすべて表示します。

すべての一致を表示する完全に移植可能な唯一の方法は、$PATH自分自身を解析することです。これを行うシェルスクリプトを次に示します。シェル関数にする場合は、関数本体を括弧で囲み(関数が変更さIFSset -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正常に動作するようです。
ステファンシャゼル

5

--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ここでは役に立ちません。私の答えをご覧ください。
ジル 'SO-悪である停止

ネストされたディレクトリでは確かに遅いので、間違っていると感じることがわかっています。グロビングと$ PATHのスペース?うわー。しかし、あなたは正しい(あなたはそれほど多くは言わなかったけど):私のライナーは不十分に書かれていた。
エリヘディ

1

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保護されていない上グロブオフにします$PATHtest -fここでは実行可能ファイルのみが必要なので、十分ではありません。あなたが必要test -xです。うーん、スクリプトで通常のファイルテストを忘れていたことがわかりました。
ジル 'SO-悪であるのをやめる'

@Gilles:ヒントに従って編集します。私はすべて正しいことを望んでいますが、私はwhence README.txtそうではないと思いますwhence "file* wi?h we!rd name"。横断するのがどれほど簡単かを示すだけ$PATHです。
マット・ビアンコ

0

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

私も言わなければならない、それは潜在的に有用な動作のようです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.