Um shell conhece quatro tipos de comandos.
- Aliases: são apelidos para um comando com algumas opções. Eles são definidos no arquivo de inicialização do shell (
~/.bashrc
for bash).
- Funções: eles são trechos de código de shell dado um nome. Como os aliases, eles são definidos no arquivo de inicialização do shell.
- Builtins: o shell vem com um pequeno número de comandos internos. A maioria dos builtins manipula o estado do shell (
cd
altera o diretório atual, set
altera opções e parâmetros posicionais, export
altera o ambiente,…). A maioria dos shell oferece basicamente os mesmos recursos internos, mas cada shell tem algumas extensões para o conjunto básico.
- Comandos externos: eles são independentes do shell. Como outros programas, o shell executa programas externos pesquisando-os no caminho de pesquisa executável . A variável de ambiente
PATH
contém uma lista de diretórios separados por dois-pontos para pesquisar programas.
Caso haja comandos de vários tipos com o mesmo nome, a primeira correspondência na ordem acima é executada¹.
Você pode ver a que tipo de comando um nome corresponde executando type some_name
.
Você pode listar aliases executando o alias
integrado sem argumento. Não há como listar funções ou builtins que funcionem em todos os shells. Você pode encontrar uma lista de builtins na documentação do shell.
No bash, o set
builtin lista funções com suas definições, bem como variáveis. No bash, ksh ou zsh, typeset -f
lista funções com suas definições. No bash, você pode listar todos os nomes de comandos de qualquer tipo com compgen -c
. Você pode usar compgen -A alias
, compgen -A builtin
compgen -A function
para listar comandos de um tipo específico. Você pode passar uma string adicional para compgen
para listar apenas os comandos que começam com esse prefixo.
Em zsh, você pode listar os comandos atualmente disponíveis de um determinado tipo com echo ${(k)aliases}
, echo ${(k)functions}
, echo ${(k)builtins}
e echo ${(k)commands}
(esse último lista apenas os comandos externos).
O snippet de agnóstico de shell lista todos os programas externos disponíveis:
case "$PATH" in
(*[!:]:) PATH="$PATH:" ;;
esac
set -f; IFS=:
for dir in $PATH; do
set +f
[ -z "$dir" ] && dir="."
for file in "$dir"/*; do
if [ -x "$file" ] && ! [ -d "$file" ]; then
printf '%s = %s\n' "${file##*/}" "$file"
fi
done
done
Há um caso de borda nos comandos Bash: hash.
Manual de referência do Bash diz:
A full search of the directories in $PATH is performed only if the command is not found in the hash table
Tente:
set -h
mkdir ~/dir-for-wat-command
echo 'echo WAT!' >~/dir-for-wat-command/wat
chmod +x ~/dir-for-wat-command/wat
hash -p ~/dir-for-wat-command/wat wat
wat
A variável de ambiente PATH
não contém ~/dir-for-wat-command
, compgen -c
não mostra wat
, mas você pode executar wat
.
Se você quiser sombrear um comando existente, defina um alias ou uma função .
¹ Exceção: alguns builtins (chamados de builtins especiais ) não podem ser sombreados por uma função - o bash e o zsh não estão em conformidade com o POSIX nesse ponto em seu modo padrão.