Por que o `tipo que` diz o` que está com hash`?

31

No caso de shell-builtins (por exemplo, typeele próprio):

$ type type
type is a shell builtin

$ which type
<Doesn't return anything since it's a shell builtin, silently exits>

No caso de comandos (normalmente) (por exemplo python):

$ type python
python is /usr/bin/python

$ which python
/usr/bin/python

No caso de which(que é um comando localizado em /usr/bin/which)

$ type which
which is hashed (/usr/bin/which)
$ which which
/usr/bin/which

Por que type whichdiz isso which is hashed? Qual é o significado de whichser hash e o que realmente significa?

Aditya
fonte

Respostas:

40

Você provavelmente tem um longo caminho PATH e, para encontrar um executável, o shell precisa pesquisar o caminho. Para evitar esse processo demorado toda vez que você deseja executar um programa, o shell pode manter uma lista dos programas que ele já encontrou. Essa lista é chamada de "hash". Quando o shell diz que whichestá com hash, significa que já fez a pesquisa PATH e encontrou whiche salvou sua localização no hash.

man bash explica o seguinte:

O Bash usa uma tabela de hash para lembrar os nomes de caminho completos dos arquivos executáveis ​​(consulte o hash em SHELL BUILTIN COMMANDS abaixo). Uma pesquisa completa dos diretórios no PATH é executada apenas se o comando não for encontrado na tabela de hash.

Enquanto o hash normalmente acelera as operações do shell, há um caso em que causa problemas. Se você atualizar seu sistema e, como resultado, alguns executáveis ​​forem movidos para um novo local, o shell poderá ficar confuso. A solução é executar, o hash -rque faz com que o shell esqueça todos os locais de hash e procure o PATH do zero.

Por que alguns executáveis ​​estão ausentes no hash?

Um executável não é colocado no hash até que você execute pelo menos uma vez. Observar:

$ type python
python is /usr/bin/python
$ python --version
Python 2.7.3
$ type python
python is hashed (/usr/bin/python)

python é hash somente depois de executado.

Como examinar o que está no hash do bash

O conteúdo do hash está disponível na bashmatriz BASH_CMDS. Você pode ver o que está nele com o comando declare -p BASH_CMDS. Quando um novo shell ou subshell é aberto, o hash fica vazio. Os comandos são adicionados um a um à medida que são usados. Em um shell recém-aberto, observe:

$ declare -p BASH_CMDS
declare -A BASH_CMDS='()'
$ which which
/bin/which
$ declare -p BASH_CMDS
declare -A BASH_CMDS='([which]="/bin/which" )'
$ python --version
Python 2.7.3
$ declare -p BASH_CMDS
declare -A BASH_CMDS='([which]="/bin/which" [python]="/usr/bin/python" )'
John1024
fonte
+1, explicação muito boa. Mas por que whiche não para python?
Jobin
@Jobin Veja a resposta atualizada.
precisa saber é o seguinte
2
Parece que o hash persiste apenas até o momento em que não saímos do shell. Depois de reiniciar o terminal, ele não diz que o comando está com hash.
Aditya
1
@Aditya Sim. Eu adicionei uma seção sobre isso à resposta.
precisa saber é o seguinte
hash -lseria mais fácil de usar do quedeclare -p BASH_CMDS
phuclv