Яка мета хеш-команди?


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.

Він навіть був представлений у топ-15 корисних команд thegeekstuff.com

Якими способами hashкорисний?

Відповіді:


97

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це один із способів зробити це.

  • Ви можете використовувати його для запам'ятовування файлових шляхів. Це корисно, якщо новий виконуваний файл з'являється в попередньому 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виконуваного файлу , щоб показати раніше на мою , $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.

Існує багато подібних ситуацій. Я не знаю, чи б я назвав це однією з "найкорисніших" команд, але у неї є деякі випадки використання.


Цікаво, звідки пішла назва «хеш». Що тоді, наприклад, "кеш"? :).
Майкл

2
@Michael Оскільки hashкоманда внутрішньо використовує хеш-таблицю для зберігання відображень. en.wikipedia.org/wiki/Hash_table
jlliagre

10
Слід зазначити, що hashце не bashконкретно, команда виникла в оболонці Bourne у SVR2 (хоча функція хешування шляхів команд походить від цього cshраніше) і зустрічається у всіх оболонках Bourne та POSIX.
Стефан Шазелас

1
Замість того, export PATH=$PATHщоб очистити таблицю, hash -rповинно вистачити.
ravron

1
Інший випадок використання - це при встановленні другої копії програми в більш ранній частині вашої $ 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.
Іоанніс Філіппідіс

@johntex: добре, змінено.
rici

Уявіть собі потенціал для дивних помилок, перш ніж знати, що хеш-таблиця існує! Чи є список обставин, коли хеш-таблиця автоматично оновлюється?
benjimin

@benji: він ніколи не оновлюється автоматично (в цілому). Якщо ви запускаєте bash в режимі posix або setopt -s checkhashі хешований виконуваний файл для команди більше не існує, хеш-запис для цієї команди буде оновлений. Але зауважте, що кожен баш-сеанс мав свою хеш-таблицю, тому закриття сеансу та запуск нового ефективно очищає хеш. ( hash -rце простіший спосіб зробити це.)
rici

Оновлення $PATHабо запуск нового терміналу bash, як видається, очищають таблицю.
benjimin

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

Так, Довідковий посібник Баша говорить:

Повний пошук каталогів у $ PATH виконується лише в тому випадку, якщо команда не знайдена в хеш-таблиці.

Але ви можете відключити хешування з set +h:

-h - Знайдіть і запам’ятайте (хеш) команди, коли їх шукають для виконання. Ця опція включена за замовчуванням.

Спробуйте:

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

Те ж саме для hash -r, і hash 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.