web-dev-qa-db-fra.com

Quel est le but de la commande de hachage?

Si vous exécutez hash, il indique le chemin de toutes les commandes exécutées depuis la dernière réinitialisation du hachage (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

Selon les pages de manuel, le but du hachage est:

L'utilitaire/usr/bin/hash affecte la façon dont l'environnement Shell actuel se souvient des emplacements des utilitaires trouvés. Selon les arguments spécifiés, il ajoute des emplacements d'utilitaires à sa liste d'emplacements mémorisés ou il purge le contenu de la liste. Lorsqu'aucun argument n'est spécifié, il rend compte du contenu de la liste. Le -r L'option fait que le shell oublie tous les emplacements mémorisés.

Les utilitaires fournis en tant qu'éléments intégrés au shell ne sont pas signalés par le hachage.

A part voir combien de fois j'ai entré une commande, je ne vois pas l'utilité de hash.

Il a même été présenté dans thegeekstuff.com's top 15 commandes utiles

En quoi hash est-il utile?

122
spuder

hash est une commande intégrée bash. La table de hachage est une fonctionnalité de bash qui l'empêche d'avoir à rechercher $PATH chaque fois que vous tapez une commande en mettant en cache les résultats en mémoire. Le tableau est effacé sur les événements qui invalident évidemment les résultats (tels que la modification de $PATH)

La commande hash est simplement la façon dont vous interagissez avec ce système (pour la raison que vous jugez nécessaire).

Quelques cas d'utilisation:

  • Comme vous l'avez vu, il affiche le nombre de fois que vous appuyez sur les commandes si vous le tapez sans argument. Cela pourrait vous indiquer les commandes que vous utilisez le plus souvent.

  • Vous pouvez également l'utiliser pour mémoriser les exécutables dans des emplacements non standard.

Exemple:

[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 ~]#

Ce qui peut être utile si vous n'avez qu'un seul exécutable dans un répertoire en dehors de $PATH que vous souhaitez exécuter en tapant simplement le nom au lieu d'inclure tout dans ce répertoire (ce qui serait l'effet si vous l'ajoutiez à $PATH).

Un alias peut généralement le faire également, et comme vous modifiez le comportement du shell actuel, il n'est pas mappé dans les programmes que vous démarrez. Un lien symbolique vers le seul exécutable est probablement l'option préférable ici. hash est une façon de le faire.

  • Vous pouvez l'utiliser pour ne plus vous souvenir des chemins de fichiers. Ceci est utile si un nouvel exécutable apparaît dans un répertoire PATH antérieur ou obtient mv 'd ailleurs et que vous voulez forcer bash à sortir et à le retrouver à la place du dernier endroit il se souvient de l'avoir trouvé.

Exemple:

[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 ~]#

La commande cp a fait apparaître une nouvelle version de l'exécutable ls plus tôt dans mon $PATH mais n'a pas déclenché de purge de la table de hachage. J'ai utilisé hash -d pour purger sélectivement l'entrée de ls de la table de hachage. Bash a ensuite été contraint de regarder à travers $PATH encore et quand il l'a fait, il l'a trouvé dans le nouvel emplacement (plus tôt dans $ PATH qu'il ne fonctionnait auparavant).

Vous pouvez invoquer de manière sélective ce "rechercher un nouvel emplacement d'exécutable à partir de $PATH ", cependant:

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

Vous voudriez surtout le faire si vous vouliez quelque chose hors de la table de hachage et que vous ne pouviez pas vous déconnecter à 100% puis vous reconnecter avec succès, ou si vous vouliez conserver certaines modifications que vous avez apportées à votre shell.

Pour vous débarrasser des mappages périmés, vous pouvez également faire hash -r (ou export PATH=$PATH) qui purge efficacement la table de hachage entière de bash.

Il y a beaucoup de petites situations comme ça. Je ne sais pas si je l'appellerais l'une des commandes "les plus utiles" mais elle a quelques cas d'utilisation.

100
Bratchley

Voici l'utilisation classique, simplifiée:

# 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

Voici une utilisation utile de hash:

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

Cela signifie: si php n'est pas dans le CHEMIN, alors utilisez

/usr/local/foobar/php/bin/
18
Gilles Quenot

Oui, Bash Reference Manual dit:

Une recherche complète des répertoires dans $ PATH n'est effectuée que si la commande n'est pas trouvée dans la table de hachage.

Mais vous pouvez désactiver le hachage avec set +h:

-h - Recherchez et mémorisez les commandes (hachage) lors de leur recherche pour exécution. Cette option est activée par défaut.

Essayer:

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

Il en va de même pour hash -r, hash NAME etc

Une "détection de commande" (comme this ou that ) ne fonctionne pas:

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

Vous pouvez écrire quelque chose comme ceci:

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

ou (grâce à @mikeserv) sans devoir assigner de nouvelles variables ni faire de tests:

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

Détection facile si une commande est disponible:

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