Linux / Comando command: executar sem chamar funções do Bash
command é um comando interno do shell que executa um comando sem procurar uma função de mesmo nome. Ele ainda pode escolher um comando interno ou um arquivo de PATH. Use command nome para executar e command -v nome para consultar se o nome é reconhecido no shell atual.
Shell é o interpretador de comandos, e PATH é sua lista de diretórios de busca. No Bash, -V fornece uma descrição detalhada e -p usa o caminho padrão para encontrar utilitários do sistema. Este artigo distingue essas consultas da execução e compara command com builtin, exec e env.
O que é o comando command?
Uma função de shell pode ter o mesmo nome de um comando externo. Neste caso, chamar o nome diretamente dentro da função pode fazer com que ela se chame novamente, levando à recursão. Antepor command ignora a função de shell com o mesmo nome e seleciona o comando builtin do Bash ou o executável encontrado em PATH.
command é um comando interno do Bash e de vários outros shells, não uma função definida pelo usuário. A especificação POSIX de command define seu comportamento básico; os exemplos seguintes usam Bash. As frases de saída e algumas particularidades variam entre shells.
Sintaxe básica
command [-pVv] nome [argumentos ...]
O bloco anterior é um esquema de sintaxe: colchetes e reticências indicam partes opcionais, não texto a copiar literalmente. Sem -v ou -V, command executa o nome indicado. Os exemplos abaixo listam o diretório atual, incluindo arquivos ocultos, e depois imprimem hello.
command ls -la
command printf '%s\n' 'hello'
Na maioria das situações, parece que o comando foi executado diretamente. A diferença se torna aparente quando existe uma função de shell com o mesmo nome.
Chamar o comando sem recursão dentro de uma função
Salve o exemplo completo abaixo como listar.sh e execute bash listar.sh -la. Ele requer Bash e GNU ls, pois usa --color=auto. A função imprime uma mensagem e encaminha as opções e caminhos recebidos para o ls externo; ela só existe no processo desse script, sem substituir uma função do terminal pai.
#!/usr/bin/env bash
ls() {
printf '%s\n' 'Exibindo a lista.'
command ls --color=auto "$@"
}
ls "$@"
Se a função usasse ls "$@" dentro de si, voltaria a chamar a própria função. command ls ignora essa busca; no Bash padrão, em que ls não é um comando interno, o arquivo encontrado em PATH é executado. O estado retornado por ele também será o estado final da função e deste script.
"$@" preserva cada argumento recebido. Por exemplo, bash listar.sh -d -- "pasta com espaços" deve tratar esse caminho existente como um único argumento. $* ou $@ sem aspas pode dividir espaços e expandir curingas. Para interromper a personalização, deixe de usar o arquivo do exemplo; nenhuma configuração persistente do shell foi alterada.
Consultar um nome com command -v
-v consulta como o nome é reconhecido no ambiente atual, sem executá-lo. Retorna 0 quando o encontra e um valor diferente de zero quando não o encontra. Nos exemplos abaixo, cd e printf normalmente são impressos como nomes de comandos internos; git pode produzir um caminho, se estiver instalado e não for ocultado por outra definição.
command -v git
command -v cd
command -v printf
A saída também pode representar função, alias ou palavra reservada, e não precisa ser um caminho de arquivo. O trecho seguinte apenas informa se curl é reconhecido, sem executá-lo nem testar conexão com a rede. A mensagem impressa não garante que o programa realizará uma operação específica; se a ausência deve encerrar um script, use o exemplo de pré-requisito mais adiante.
if command -v curl >/dev/null 2>&1; then
printf '%s\n' 'curl é reconhecido pelo shell.'
else
printf '%s\n' 'curl não foi encontrado.' >&2
fi
Ver detalhes com command -V
-V produz uma descrição mais detalhada. deploy abaixo é apenas um nome de exemplo: pode ser uma função local, mas a consulta falha se ele não estiver definido. Essas linhas não executam os nomes consultados.
command -V ls
command -V cd
command -V deploy
Não analise as frases de -V em automação: elas variam com o shell e o idioma. Para consultar a disponibilidade de um nome, use o estado de saída de command -v. Uma função reconhecida nessa consulta pode ser ignorada por command nome na execução; os dois modos têm finalidades diferentes.
command -p e o caminho de busca padrão
-p usa o caminho padrão fornecido pelo shell para encontrar utilitários padronizados. command -p getconf PATH consulta o valor padrão de PATH do sistema; command -p ls lista o diretório usando essa busca. Isso não muda o valor de PATH para comandos seguintes.
command -p getconf PATH
command -p ls
O caminho padrão varia entre sistemas. -p ainda permite comandos internos e não fixa um fornecedor nem uma versão do programa. Ele ajuda na busca de utilitários, mas não substitui o controle de permissões e de diretórios em scripts que dependem de um ambiente confiável.
Resumo das opções de command
| Opção | Descrição |
|---|---|
-v |
Exibe de forma concisa a interpretação do shell atual sem executar o comando. |
-V |
Imprime uma explicação detalhada de como o comando é interpretado. |
-p |
Executa um comando usando o caminho de busca padrão onde utilitários padrão podem ser encontrados. |
Como command interage com aliases
Aliases são expandidos quando o shell lê o comando, antes da execução. Normalmente, command ls deixa ls fora da posição sujeita à expansão de alias e ignora a função de mesmo nome. Porém, o próprio nome command pode ter sido redefinido como alias ou função; em Bash, um alias terminado em espaço também afeta a expansão da palavra seguinte. Confira as regras de aliases ao diagnosticar essas personalizações.
Use type para inspecionar as categorias e os candidatos no Bash. No exemplo abaixo, type -a ls lista os candidatos, e command -V ls descreve o nome em modo de consulta.
type -a ls
command -V ls
Uma barra invertida em \ls impede a expansão desse alias, mas não ignora uma função ls. Um caminho absoluto evita a busca por nome. As duas linhas abaixo executam o nome ou caminho indicado; quando chegam ao ls externo, listam o diretório atual.
\ls
/usr/bin/ls
Confirme o caminho com type -P ls antes de usar /usr/bin/ls, pois ele pode variar. Nenhuma dessas formas transforma texto arbitrário em entrada segura: aspas e limites dos argumentos continuam necessários.
Comparar command, builtin, exec e env
| Comando | Funções Principais |
|---|---|
command nome |
Ignora funções de mesmo nome e executa um comando interno ou um arquivo encontrado em PATH. |
builtin nome |
Executa explicitamente um comando interno do Bash com o mesmo nome. |
exec nome |
Substitui o processo shell atual por um novo programa. Se bem-sucedido, não retorna ao shell original. |
env VAR=valor nome |
Executa um comando externo em um ambiente com variáveis de ambiente ajustadas. |
type nome |
Mostra como o Bash atual interpreta um nome sem executar o comando. |
Use builtin nome quando precisar explicitamente do comando interno do Bash. Use command nome quando quiser ignorar funções e permitir tanto um comando interno quanto um arquivo externo. A documentação de exec explica a diferença entre substituir o processo e apenas executar um comando.
Usar command -v em scripts
Verificar um pré-requisito pelo estado de saída
Salve como verificar-rsync.sh e execute bash verificar-rsync.sh. Esse teste requer apenas Bash: se rsync não for reconhecido, imprime o diagnóstico e termina com estado 1. Se for reconhecido, imprime a confirmação e termina com 0; não inicia sincronização alguma.
#!/usr/bin/env bash
if ! command -v rsync >/dev/null 2>&1; then
printf '%s\n' 'rsync é necessário.' >&2
exit 1
fi
printf '%s\n' 'rsync é reconhecido pelo shell.'
O espaço entre if e ! é necessário. A construção verifica o estado, sem depender do formato da saída de consulta. >/dev/null 2>&1 descarta a saída e os diagnósticos da consulta; a mensagem útil é escrita pelo próprio script. Confira o resultado com echo "$?" imediatamente após executá-lo.
Exigir um arquivo externo executável
command -v também reconhece comandos internos e funções. Apenas aplicar -f e -x ao texto retornado pode gerar um falso positivo se ele for um nome como printf e houver um arquivo homônimo no diretório atual. O exemplo Bash abaixo exige primeiro que a resolução normal seja file, depois confere o arquivo retornado.
Salve como verificar-arquivo.sh e execute bash verificar-arquivo.sh ls. Em uma instalação com ls externo, ele imprime o caminho e retorna 0. Experimente bash verificar-arquivo.sh cd: como cd é interno, o exemplo o rejeita com estado 1, sem executá-lo.
#!/usr/bin/env bash
if [ "$#" -ne 1 ]; then
printf '%s\n' 'Uso: bash verificar-arquivo.sh nome' >&2
exit 1
fi
if [ "$(type -t -- "$1")" != file ]; then
printf '%s\n' 'O nome não resolve para um arquivo externo.' >&2
exit 1
fi
tool_path=$(command -v -- "$1") || exit 1
if [ -f "$tool_path" ] && [ -x "$tool_path" ]; then
printf 'Arquivo executável: %s\n' "$tool_path"
else
printf '%s\n' 'O caminho não é um arquivo regular executável.' >&2
exit 1
fi
Este segundo exemplo usa type -t, portanto requer Bash e não é um script POSIX genérico. Ele consulta o processo Bash iniciado pelo arquivo, que pode não ter aliases e funções locais do terminal. Caminhos relativos e entradas do hash ainda dependem do ambiente. Para procurar um executável mesmo quando uma função ou comando interno tem prioridade, use type -P nome, sabendo que essa é outra pergunta.
Entender o intervalo entre verificar e executar
TOCTOU significa time of check to time of use: o intervalo entre verificar e usar um recurso. Entre a consulta e a execução, o arquivo ou PATH pode mudar. Esses testes ajudam a apresentar diagnósticos, mas não garantem identidade, versão, permissão de acesso aos dados nem comportamento futuro. Use caminhos e permissões controlados quando isso for necessário.
Estado de saída
Em Bash, o comando executado normalmente fornece o estado final. Um nome não encontrado produz 127; um arquivo encontrado que não pode ser executado pode produzir 126. Outras falhas, como opção inválida ou redirecionamento, podem ter estados diferentes. Os modos -v e -V retornam sucesso quando o nome é reconhecido e falha caso contrário; veja as regras de estado de saída do Bash.
command false
printf 'status=%d\n' "$?"
command does-not-exist
printf 'status=%d\n' "$?"
O primeiro printf acima deve imprimir status=1, pois false retorna falha. Para o nome inexistente does-not-exist, espera-se um diagnóstico e status=127, desde que não haja uma definição local com esse nome ou tratamento personalizado de comando ausente. Cada printf lê o estado da linha imediatamente anterior e depois retorna seu próprio estado; o bloco inteiro não preserva o 127.
Perguntas frequentes
command executa somente arquivos externos?
Não. No Bash, ele ignora funções do shell e então executa comandos internos ou comandos externos encontrados no PATH. Para encontrar apenas arquivos externos, você precisa verificar o caminho usando ferramentas como type -P.
O resultado de command -v é sempre um caminho absoluto?
Não. O resultado pode vir de aliases, funções, palavras reservadas, comandos internos ou arquivos executáveis. Use o status de saída para verificar a existência de um comando.
Posso usar sudo command...?
Como command é um comando interno do shell, sudo pode não ser capaz de executá-lo diretamente como um executável separado. Normalmente, você passa o comando externo necessário diretamente para sudo, ou, se a sintaxe do shell for necessária, você deve executar explicitamente o shell enquanto entende as implicações de aspas e segurança.
Quando preferir command -v a which?
command -v é fornecido pelo shell e reflete a interpretação de comandos do shell atual. which é frequentemente um programa externo e, dependendo de sua implementação, pode não lidar corretamente com aliases ou funções.
Como ignorar funções e executar só o comando interno?
No Bash, use builtin nome. command nome pode executar não apenas comandos internos, mas também comandos externos em PATH.
As mesmas opções podem ser usadas em outros shells?
As operações principais de -p, -v e -V são definidas no POSIX, mas as mensagens de saída e recursos estendidos podem variar de um shell para outro. Para automação, especifique o shell de destino e verifique sua documentação.
Resumo
command é útil para chamar o comando original que pode estar oculto por uma função do shell e verificar se o comando pode ser encontrado no shell atual. Use command nome para executar, command -v nome para verificar existência e command -V nome para uma descrição detalhada legível por humanos.
Para entender uma resolução inesperada, combine a consulta com type -a nome. A referência de comandos Linux em português reúne outros comandos por tarefa.




