ハッシュコマンドの目的は何ですか?


118

実行するhashと、ハッシュが最後にリセットされてから実行されたすべてのコマンドのパスが表示されます(hash -r

[root@c04c ~]# hash
hash: hash table empty

[root@c04c ~]# whoami
root

[root@c04c ~]# hash
hits    command
   1    /usr/bin/whoami

[root@c04c ~]# whoami
root

[root@c04c ~]# hash
hits    command
   2    /usr/bin/whoami

マニュアルページによると、ハッシュの目的は次のとおりです。

/ usr / bin / hashユーティリティは、現在のシェル環境が見つかったユーティリティの場所を記憶する方法に影響します。指定された引数に応じて、記憶されている場所のリストにユーティリティの場所を追加するか、リストの内容を削除します。引数が指定されていない場合、リストの内容について報告します。この-rオプションにより、シェルは記憶されているすべての場所を忘れます。

シェルにビルトインとして提供されるユーティリティは、ハッシュによって報告されません。

コマンドを何回入力したかを確認する以外に、のユーティリティが表示されませんhash

thegeekstuff.comのトップ15の便利なコマンドにも取り上げられました

どのような点でhash便利ですか?

回答:


97

hashbash組み込みコマンドです。ハッシュテーブルは、結果をメモリにキャッシュすることにより、コマンドを入力するたびbash に検索する必要がないようにする機能です$PATH。結果を明らかに無効にするイベント(変更など$PATH)でテーブルがクリアされます

hashコマンドは、あなたが(あなたがする必要があると感じ方の理由で)そのシステムと対話するだけの方法です。

いくつかのユースケース:

  • あなたが見たように、引数なしで入力した場合、どのコマンドを何回ヒットしたかを出力します。これにより、最も頻繁に使用するコマンドがわかります。

  • また、これを使用して、非標準の場所にある実行可能ファイルを記憶することもできます。

例:

[root@policyServer ~]# hash -p /lol-wut/whoami whoami
[root@policyServer ~]# whoami
Not what you're thinking
[root@policyServer ~]# which whoami
/usr/bin/whoami
[root@policyServer ~]# /usr/bin/whoami
root
[root@policyServer ~]#

それは$PATH、そのディレクトリのすべてを含めるのではなく、名前を入力するだけで実行したい外部のディレクトリに単一の実行可能ファイルがある場合に便利です(これを追加すると効果があります$PATH)。

エイリアスは通常これを行うこともできますが、現在のシェルの動作を変更しているため、キックオフするプログラムにはマップされません。ここでは、おそらく単独の実行可能ファイルへのシンボリックリンクが望ましいオプションです。hashそれを行う1つの方法です。

  • これを使用して、ファイルパスを記憶することができます。これは、新しい実行可能ファイルが以前のPATHディレクトリにポップアップしたり、mv別の場所に移動したりして、bashを強制的に終了させて​​、最後に見つけた場所ではなく再び見つけたい場合に便利です。

例:

[root@policyServer ~]# hash
hits    command
   1    /bin/ls
[root@policyServer ~]# cp /bin/ls /lol-wut
[root@policyServer ~]# hash
hits    command
   1    /bin/cp
   1    /bin/ls
[root@policyServer ~]# hash -d ls
[root@policyServer ~]# ls
default.ldif  newDIT.ldif  notes.txt  users.ldif
[root@policyServer ~]# hash
hits    command
   1    /bin/cp
   1    /lol-wut/ls
[root@policyServer ~]#

このcpコマンドにより、新しいバージョンのls実行可能ファイルがmyの前に表示されました$PATHが、ハッシュテーブルのパージはトリガーされませんでした。ハッシュテーブルからhash -d選択的にエントリを削除するために使用していましたls。その後、Bashは$PATH再度調べなければならなかったため、新しい場所(以前実行していたよりも$ PATHで以前)で見つけました。

$PATHただし、この「実行可能ファイルの新しい場所を見つける」動作を選択的に呼び出すことができます。

[root@policyServer ~]# hash
hits    command
   1    /bin/ls
[root@policyServer ~]# hash ls
[root@policyServer ~]# hash
hits    command
   0    /lol-wut/ls
[root@policyServer ~]#

ハッシュテーブルから何かを望んでいて、ログアウトしてから正常に戻ることができなかった場合、またはシェルに加えた変更を保存したい場合は、たいていこれを行うだけです。

古いマッピングを取り除くために、bashのハッシュテーブル全体を効果的に削除するhash -r(またはexport PATH=$PATH)こともできます。

そのような小さな状況がたくさんあります。「最も便利な」コマンドの1つと呼ぶかどうかはわかりませんが、いくつかの使用例があります。


「ハッシュ」という名前はどこから来たのだろうか。たとえば、「キャッシュ」はどうですか?:)。
マイケル

2
@Michael hashコマンドは内部的にハッシュテーブルを使用してマッピングを保存するため。en.wikipedia.org/wiki/Hash_table
jlliagre

10
コマンドhashbash特定ではなく、SVR2のBourneシェルで生成され(コマンドのハッシュパスの機能はcshその前にあります)、すべてのBourneライクおよびPOSIXシェルで見つかることに注意してください。
ステファンシャゼル

1
export PATH=$PATHテーブルをクリアする代わりに、hash -r十分なはずです。
-ravron

1
別の使用例は、プログラムの2番目のコピーを$ PATHの以前の部分にインストールする場合です。hash -r$ PATHは変更されなかったため、古いバージョンを取得する必要があります。したがって、Bashは以前の(優先度の高い)ディレクトリから同じプログラムをロードできることを認識していません。詳細については、conda.pydata.org / docs /…を参照してください。
ジョンツウィンク

37

古典的な使用法を簡単に示します。

# My PATH contains /home/rici/bin as well as the Usual Suspects:
# (the real one has lots more)
$ echo $PATH
/home/rici/bin:/usr/local/bin:/usr/bin:/bin

# I've installed a program called hello in /usr/local/bin
$ $ cat /usr/local/bin/hello
#!/bin/bash

echo Hello, world. I live at $0

# The program works.
$ hello
Hello, world. I live at /usr/local/bin/hello

# Now I want to create a better hello, just for me. I put it in
# my own bin directory, and according to my PATH, it should come first.
$ cp /usr/local/bin/hello ~/bin/hello

# So now I will try running it
$ hello
Hello, world. I live at /usr/local/bin/hello

# WTF? Oh, forgot to run hash.
# Tell bash to update where to look for hello
$ hash hello
$ hello
Hello, world. I live at /home/rici/bin/hello

# Ah, all is well.

ここで述べたように、単一のコマンドでハッシュテーブルの選択的な更新を呼び出すことができますhash hello
イオアニスフィリピディス14

@johntex:OK、変更されました。
リチ14

ハッシュテーブルが存在することを知る前に、奇妙なバグの可能性を想像してください!ハッシュテーブルが自動的に更新される状況のリストはありますか?
ベンジミン

@benji:(全体として)自動的に更新されることはありません。posixモードでbashをsetopt -s checkhash実行するか、コマンドのハッシュ化された実行可能ファイルが存在しない場合、そのコマンドのハッシュエントリが更新されます。ただし、すべてのbashセッションには独自のハッシュテーブルがあるため、セッションを閉じて新しいセッションを開始すると、ハッシュが事実上空になります。(hash -rそれを行う簡単な方法です。)
rici

更新$PATHするか、新しいbashターミナルを起動すると、両方ともテーブルが消去されます。
ベンジミン

17

の便利な使用法はhash次のとおりです。

hash php 2> /dev/null || hash -p /usr/local/foobar/php/bin/php php 2> /dev/null

つまり、phpがPATHにない場合は、次を使用します。

/usr/local/foobar/php/bin/

8

はい、Bashリファレンスマニュアルには次のように記載されています。

コマンドがハッシュテーブルで見つからない場合にのみ、$ PATH内のディレクトリの完全検索が実行されます。

ただし、次の方法でハッシュを無効にできますset +h

-h-実行のために検索されるコマンドを見つけて記憶(ハッシュ)します。このオプションはデフォルトで有効になっています。

試してください:

set +h
hash # prints bash: hash: hashing disabled
echo $? # prints 1

同じことがあるためhash -rhash NAMEなど

「コマンド検出」(これまたはそのような)は機能しません:

set -h
hash ls >/dev/null 2>&1 || echo "Please install ls" >&2 # prints nothing

set +h
hash ls >/dev/null 2>&1 || echo "Please install ls" >&2 # prints Please install ls

このようなものを書くことができます:

old_options="$-"
set -h
hash ls >/dev/null 2>&1 || echo "Please install ls" >&2
[[ "$old_options" =~ "h" ]] || set +h

または(@mikeservに感謝)新しい変数を割り当てたり、テストを実行したりする必要はありません。

set -h -- "-${-:--}" "$@"
hash ls >/dev/null 2>&1 || echo "Please install ls" >&2
set +h "$@"

1
あなたのold_optionsことのために-私は通常このようなことをします:set -h -- "-${-:--}" "$@"; hash ...; set +h "$@"したがって、新しい変数を割り当てたり、テストなどを行う必要なく、すべて自動的に所定の位置に落ちます。
mikeserv

5

コマンドが使用可能かどうかの簡単な検出:

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