web-dev-qa-db-ja.com

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

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

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

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

シェルに組み込みで提供されるユーティリティは、ハッシュでは報告されません。

コマンドを何回入力したかを見る以外に、hashのユーティリティを見ることができません。

Geekstuff.comの 上位15の便利なコマンド でも紹介されました

hashはどのように役立ちますか?

122
spuder

hashは、bash組み込みコマンドです。ハッシュテーブルは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 'dされ、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実行可能ファイルが$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 ~]#

ハッシュテーブルから何かが必要で、ログアウトして正常に再度ログインできる100%でない場合や、シェルに加えた変更を保持したい場合は、ほとんどの場合これを行います。

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

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

100
Bratchley

以下は、簡略化された従来の使用方法です。

# 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.
40
rici

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/
18
Gilles Quenot

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

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

ただし、set +hを使用してハッシュを無効にすることができます。

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

試してください:

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

hash -rhash NAMEなども同様です

「コマンド検出」( this または that など)は機能しません。

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 "$@"
8

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

CMD=gzip
if hash bzip2; then
    CMD=$_
fi
6
brablc