web-dev-qa-db-ja.com

私の `which`コマンドは間違っているかもしれません(時々)?

私のマシンにインストールされているバージョンは(かなり)私にとって古い(v21.3)ので、ソースコード(v24.2)から最後のemacsバージョンをコンパイルしました。私はいつも通りにやった:

$configure --prefix=$HOME
make 
make install

今、私はemacsをテストしていて、それでも以前のバージョンが起動することに気づきました...私の$HOME/binパスはシステムのパスを上書きすることになっています(.bashrcファイルの$ PATHの前に追加されているため)。

私の最初の考えは、whichコマンドの出力を確認することでした。そして驚いたことに、それは新しいemacsへのパスを提供します。ここで矛盾がどこにあるのか理解できません。同じセッションでここに異なる出力があります:

$ emacs --version
GNU Emacs 21.3.1

$ `which emacs` --version
GNU Emacs 24.2.1

Emacsに関するエイリアスはありません。全然。

$ alias | grep emacs
$

何が起こっているのでしょうか?

18
yves Baumes

私に思い浮かぶ3つの可能性:

  • emacsのエイリアスが存在します(確認しました)
  • emacsの関数が存在します
  • 新しいemacsバイナリがシェルのPATHハッシュテーブルにありません。

関数emacsがあるかどうかを確認できます。

bash-3.2$ declare -F | fgrep emacs
declare -f emacs

そしてそれを削除します:

unset -f emacs

シェルには、PATHの各バイナリへの参照を含むPATHハッシュテーブルもあります。 PATHの他の場所にある既存のバイナリと同じ名前の新しいバイナリを追加する場合は、ハッシュテーブルを更新してシェルに通知する必要があります。

hash -r

追加説明:

whichは、bash組み込み関数ではないため、関数については知りません。

bash-3.2$ emacs() { echo 'no emacs for you'; }
bash-3.2$ emacs
no emacs for you
bash-3.2$ which emacs
/usr/bin/emacs
bash-3.2$ `which emacs` --version | head -1
GNU Emacs 22.1.1

このスクリプトでは、新しいバイナリハッシュテーブルの動作が示されています。

bash-3.2$ PATH=$HOME/bin:$PATH
bash-3.2$ cd $HOME/bin

bash-3.2$ cat nofile
cat: nofile: No such file or directory
bash-3.2$ echo echo hi > cat
bash-3.2$ chmod +x cat
bash-3.2$ cat nofile
cat: nofile: No such file or directory

bash-3.2$ hash -r
bash-3.2$ cat nofile
hi
bash-3.2$ rm cat
bash-3.2$ cat nofile
bash: /Users/mrb/bin/cat: No such file or directory

bash-3.2$ hash -r
bash-3.2$ cat nofile
cat: nofile: No such file or directory

呼んでいないけどwhich catはシェルのハッシュテーブルを使用しないため、常にPATHの最初のcatを返します。

30
mrb

はい、 どちらも使用しないでください

  • 一部のシステムでは、それはcshスクリプトとして実装された外部コマンドであり、PATHを変更する構成を読み取る可能性があります。
  • そのためのビルトインがあります。 2つ、typecommand。 POSIXの方法:

    command -v emacs       # machine-readable format
    type emacs             # human-only format
    

    Bashでは、type -p emacsを使用して、外部コマンドのパスのみを表示することもできます。

ただし、ここではwhichが実際に正しいです。 Bashはコマンドの場所に関する情報をメモリに保持するため、次回コマンドをより速く実行できます。 emacsに新しいPATH実行可能ファイルをインストールしましたが、bashのキャッシュには古い場所が残っています。 hash emacsを実行してemacsをもう一度検索するか、hash -rを実行してキャッシュを空にします。

ログアウトしてログインし、更新された.bashrcログインファイルを再読み込みしますか?そうでない場合は、現在のセッションの環境が更新されていません。

1
JRFerguson