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
はどのように役立ちますか?
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つを呼び出すかどうかはわかりませんが、いくつかの使用例があります。
以下は、簡略化された従来の使用方法です。
# 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
の便利な使用方法を次に示します。
hash php 2> /dev/null || hash -p /usr/local/foobar/php/bin/php php 2> /dev/null
つまり、phpがPATHにない場合は、
/usr/local/foobar/php/bin/
はい、 Bashリファレンスマニュアル は次のように述べています。
$ PATH内のディレクトリの完全検索は、コマンドがハッシュテーブルで見つからない場合にのみ実行されます。
ただし、set +h
を使用してハッシュを無効にすることができます。
-h-コマンドが実行のために検索されるときに、コマンドを見つけて覚えます(ハッシュ)。このオプションはデフォルトで有効になっています。
試してください:
set +h
hash # prints bash: hash: hashing disabled
echo $? # prints 1
hash -r
、hash 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 "$@"
コマンドが使用可能かどうかを簡単に検出:
CMD=gzip
if hash bzip2; then
CMD=$_
fi