15%

Poupe 15% em todos os serviços

Teste as suas habilidades e obtenha Desconto em qualquer plano

Utilizar o código:

Skills
Começar a trabalhar
08.10.2024

O Comando `which` no Linux: Guia Técnico Completo com Exemplos

O comando `which` no Linux localiza o caminho absoluto de um executável ao percorrer os diretórios listados na variável de ambiente `PATH` e retornando a primeira correspondência encontrada. É um utilitário adjacente ao POSIX usado diariamente por administradores de sistemas, desenvolvedores e engenheiros DevOps para verificar localizações de binários, auditar ambientes de execução e depurar conflitos relacionados ao PATH.

Quando você executa `which python3`, o shell não pesquisa todo o sistema de arquivos — ele percorre apenas a lista de diretórios delimitada por dois pontos armazenada em `$PATH`, da esquerda para a direita, e para na primeira correspondência. Esse comportamento é tanto o seu maior ponto forte quanto a sua limitação mais importante a ser compreendida.

Sintaxe Básica

“`bash

which [options] command_name [command_name …]

“`

  • `[options]` — Flags opcionais que modificam o comportamento da saída (abordadas em detalhes abaixo).
  • `command_name` — Um ou mais nomes de executáveis que você deseja localizar.

Como o `which` Funciona Internamente

Quando você invoca `which`, ele lê o valor atual da variável de ambiente `PATH`, divide-a nos delimitadores `:` e itera por cada diretório em ordem. Para cada diretório, verifica se existe um arquivo correspondente ao nome do comando e se ele tem o bit executável definido (permissão `x`). A primeira correspondência é impressa na saída padrão.

Isso significa que `which` é totalmente dependente do estado de execução atual de `$PATH`. Se o seu `PATH` estiver mal configurado — por exemplo, um diretório personalizado aparece após `/usr/bin` em vez de antes — `which` refletirá essa má configuração exatamente, o que é precisamente por que é útil para depuração.

Para inspecionar seu `PATH` atual:

“`bash

echo $PATH

Example output:

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

“`

Casos de Uso Principais e Exemplos

Exemplo 1: Localizar um Único Executável

O uso mais fundamental é encontrar onde um binário reside:

“`bash

which python3

“`

“`

/usr/bin/python3

“`

Isso confirma que quando você digita `python3`, o sistema executa `/usr/bin/python3`. Se você compilou uma versão personalizada e a colocou em `/opt/python3.12/bin/`, mas esse diretório não está em `PATH`, `which` não o encontrará.

Exemplo 2: Consultar Múltiplos Comandos em Uma Única Execução

Você pode passar múltiplos nomes de comandos em uma única invocação, o que é eficiente ao auditar um ambiente de build:

“`bash

which python3 gcc git curl wget

“`

“`

/usr/bin/python3

/usr/bin/gcc

/usr/bin/git

/usr/bin/curl

/usr/bin/usr/bin/wget

“`

Isso é particularmente útil em scripts de validação de pipeline CI/CD, onde você precisa confirmar que todas as ferramentas necessárias estão presentes antes de um build começar.

Exemplo 3: Descobrir Todas as Instâncias com `-a`

A flag `-a` instrui o `which` a continuar pesquisando após a primeira correspondência e reportar cada instância encontrada em todos os diretórios `PATH`:

“`bash

which -a python3

“`

“`

/usr/bin/python3

/usr/local/bin/python3

“`

Isso é crítico em ambientes onde múltiplas versões do Python estão instaladas — por exemplo, um Python do sistema em `/usr/bin/python3` e uma versão gerenciada pelo pyenv em `/usr/local/bin/python3`. O binário que aparece primeiro em `PATH` é o que será executado. Se a versão errada estiver ativa, esta saída informa exatamente onde o conflito se origina.

Caso extremo do mundo real: Em servidores que executam tanto um Node.js empacotado pela distribuição quanto um Node.js gerenciado pelo nvm, `which -a node` frequentemente revela dois ou três caminhos conflitantes. Resolver isso requer reordenar as entradas `PATH` em `.bashrc` ou `.zshrc`, não reinstalar o software.

Exemplo 4: Comportamento de Resolução de Alias

O comportamento do `which` com aliases depende muito do shell e da implementação específica do `which` instalada no sistema.

Em muitas distribuições Linux, `which` é um binário externo independente (não um built-in do shell), portanto não tem acesso à tabela de aliases do shell atual. No entanto, em sistemas onde `which` é implementado como uma função de shell ou alias em si (comum em configurações zsh), ele pode resolver aliases:

“`bash

alias ls='ls –color=auto'

which ls

“`

Em um sistema zsh com o `which` baseado em função:

“`

ls: aliased to ls –color=auto

“`

Em um sistema bash com o binário externo `which`:

“`

/bin/ls

“`

Essa inconsistência é uma fonte bem conhecida de confusão e é uma das principais razões pelas quais administradores experientes preferem `type` ou `command -v` em scripts (discutido abaixo).

Exemplo 5: Usando `which` em Lógica Condicional de Scripts

Um padrão comum em scripts de shell é usar `which` para verificar uma dependência antes de prosseguir:

“`bash

if ! which docker > /dev/null 2>&1; then

echo "Docker is not installed or not in PATH. Aborting."

exit 1

fi

“`

No entanto, a abordagem mais portável e compatível com POSIX para scripts é `command -v`:

“`bash

if ! command -v docker > /dev/null 2>&1; then

echo "Docker not found."

exit 1

fi

“`

A distinção importa ao escrever scripts destinados a executar em múltiplas distribuições ou shells.

`which` vs. `type` vs. `command -v`: Uma Comparação Técnica

Essas três ferramentas atendem a necessidades sobrepostas, mas distintas. Escolher a errada para o trabalho leva a bugs sutis, especialmente em scripts de shell.

Funcionalidade`which``type``command -v`
Localiza binários externosSimSimSim
Resolve aliases do shellDependente da implementaçãoSim (sempre)Sim (sempre)
Resolve funções do shellNãoSimSim
Identifica built-ins do shellNãoSimSim
Compatível com POSIXNãoSimSim
Funciona de forma confiável em scriptsArriscadoArriscado (built-in bash)Recomendado
Formato de saídaApenas caminhoString descritivaCaminho ou definição
Pesquisa todas as entradas PATH (equivalente a `-a`)Sim (com `-a`)Sim (com `-a`)Não
Binário externo (não um built-in)SimNão (built-in)Não (built-in)

Orientação prática:

  • Use `which` interativamente no terminal quando precisar de uma consulta rápida de caminho.
  • Use `type -a` quando quiser ver todas as formas que um comando assume (alias, função, built-in e binário).
  • Use `command -v` em scripts de shell em produção para portabilidade POSIX.

`type` em Ação

“`bash

type -a python3

“`

“`

python3 is /usr/bin/python3

python3 is /usr/local/bin/python3

“`

“`bash

type ls

“`

“`

ls is aliased to `ls –color=auto'

“`

`command -v` em Ação

“`bash

command -v git

“`

“`

/usr/bin/git

“`

“`bash

command -v ll

“`

“`

ll: aliased to ls -alF

“`

Cenários Práticos de Depuração

Depurando uma Versão Incorreta do Python

Um desenvolvedor relata que `python3 –version` retorna `3.9.x` mas ele instalou `3.11` através de uma compilação personalizada. A sequência de diagnóstico:

“`bash

which python3 # Shows the first match

which -a python3 # Shows all matches

echo $PATH # Reveals directory ordering

ls -la /usr/local/bin/python3 # Checks if the custom build is symlinked correctly

“`

A correção é quase sempre um symlink ausente ou um problema de ordenação do `PATH` no arquivo de inicialização do shell.

Diagnosticando um Comando Ausente Após a Instalação

Se `which curl` não retornar nenhuma saída, o binário não está instalado ou foi instalado em um diretório fora do `PATH`. Distingua entre esses casos:

“`bash

which curl # No output = not in PATH

find /usr -name curl -type f 2>/dev/null # Search for the binary outside PATH

apt list –installed 2>/dev/null | grep curl # Check package manager

“`

Verificando Caminhos de Ferramentas Antes da Implantação

Ao configurar um novo ambiente de VPS Hosting, uma lista de verificação pré-implantação padrão deve incluir a execução de `which -a` em cada binário crítico do qual sua aplicação depende. Isso detecta desvios de ambiente entre desenvolvimento, staging e produção antes que causem falhas em tempo de execução.

Limitações Conhecidas do `which`

Compreender essas limitações evita diagnósticos incorretos em ambientes complexos:

  • Escopo apenas do `PATH`: `which` é cego a qualquer executável não acessível através do `$PATH`. Ferramentas instaladas em diretórios locais do usuário como `~/.local/bin` só serão encontradas se esse diretório estiver no `PATH`.
  • Sem consciência de built-ins do shell: Comandos como `cd`, `echo`, `alias` e `source` são built-ins do shell. `which cd` não retornará nada ou retornará um caminho para um binário externo `cd` raramente usado, dando um resultado enganoso.
  • Tabelas de alias específicas do shell: `which` como binário externo não pode ler a tabela de aliases do shell chamador. Isso o torna não confiável para introspecção de aliases no bash.
  • Transparência de symlinks: `which` reporta o caminho do symlink, não o destino resolvido. Se `/usr/bin/python3` é um symlink para `/usr/bin/python3.11`, `which python3` mostra `/usr/bin/python3`. Use `readlink -f $(which python3)` para resolver a cadeia completa.
  • Contexto `sudo`: Executar um comando com `sudo` usa o `PATH` do root, que pode diferir significativamente do `PATH` do seu usuário. `which node` como usuário regular pode retornar um caminho diferente de `sudo which node`.

Padrões Avançados

“`bash

readlink -f $(which python3)

Output: /usr/bin/python3.11

“`

Verificar Permissões de Executável Junto com o Caminho

“`bash

ls -la $(which nginx)

Output: -rwxr-xr-x 1 root root 1234567 Jan 10 2024 /usr/sbin/nginx

“`

Combinar com `xargs` para Inspeção em Lote

“`bash

echo "python3 gcc git" | xargs -n1 which

“`

Usar em Scripts de Validação de Ambiente

Em um Servidor Dedicado executando uma pilha de aplicações complexa, um script de validação de inicialização pode ser assim:

“`bash

#!/bin/bash

REQUIRED_BINS="nginx php-fpm mysql redis-cli composer"

MISSING=0

for bin in $REQUIRED_BINS; do

if ! command -v "$bin" > /dev/null 2>&1; then

echo "MISSING: $bin"

MISSING=$((MISSING + 1))

else

echo "OK: $bin -> $(which $bin)"

fi

done

[ "$MISSING" -gt 0 ] && exit 1

exit 0

“`

Notas sobre Comportamento Específico do Shell

O comportamento do `which` não é uniforme em todos os ambientes Linux:

  • Bash: `which` é tipicamente um binário externo (`/usr/bin/which`). Ele não vê aliases ou funções do bash a menos que sejam exportados.
  • Zsh: Muitas configurações zsh incluem `which` como uma função built-in do shell que resolve aliases e funções, tornando sua saída mais rica, mas também diferente do comportamento do bash.
  • Fish shell: O Fish tem seu próprio equivalente ao `which` integrado, e seu sistema de aliases (chamado `functions`) é tratado de forma diferente.
  • Alpine Linux / ambientes BusyBox: O utilitário `which` é fornecido pelo BusyBox e pode ter um conjunto de funcionalidades reduzido em comparação com o pacote GNU `which`.

Essa variabilidade é especialmente relevante ao gerenciar aplicações em contêineres ou configurar Painéis de Controle VPS onde o shell subjacente pode diferir do seu ambiente de desenvolvimento local.

Considerações de Segurança

Em ambientes sensíveis à segurança, `which` pode ser usado como uma ferramenta de auditoria leve:

  • Verificar se binários privilegiados como `sudo`, `su` ou `passwd` resolvem para caminhos de sistema esperados e não para diretórios graváveis pelo usuário anteriores no `PATH`.
  • Detectar tentativas de sequestro de PATH: se `which ls` retornar `/home/user/bin/ls` em vez de `/bin/ls`, um binário malicioso pode ter sido injetado.

“`bash

Audit critical system binaries

for cmd in sudo su passwd ssh scp; do

echo "$cmd -> $(which $cmd)"

done

“`

Este é um passo padrão ao fortalecer um servidor que hospedará Certificados SSL ou lidará com terminação TLS sensível, onde a integridade do binário é inegociável.

Ao gerenciar ambientes de Hospedagem Web Compartilhada com múltiplos usuários, verificar se diretórios graváveis pelo usuário não aparecem antes dos diretórios do sistema no `PATH` de qualquer usuário é um controle de segurança importante.

Matriz de Decisão: Quando Usar Qual Ferramenta

CenárioFerramenta Recomendada
Consulta rápida interativa de caminho`which`
Script: verificar se um comando existe`command -v`
Identificar se um comando é um alias ou função`type`
Encontrar todas as instâncias no PATH`which -a` ou `type -a`
Resolver symlinks para o binário final`readlink -f $(which …)`
Auditar sequestro de PATH`which` + inspeção manual do PATH
Scripts portáveis entre shells`command -v`

Principais Conclusões Técnicas

  • `which` pesquisa o `$PATH` da esquerda para a direita e retorna a primeira correspondência executável — a ordenação das entradas `PATH` determina diretamente qual binário é executado.
  • A flag `-a` é essencial quando múltiplas versões de uma ferramenta coexistem; nunca assuma que existe apenas uma instância sem verificar.
  • Não use `which` em scripts de shell em produção — use `command -v` para conformidade com POSIX e comportamento consistente entre bash, dash e zsh.
  • `which` não pode ver built-ins do shell, funções ou aliases definidos na sessão atual do shell quando é executado como binário externo.
  • Sempre complemente um resultado de `which` com `readlink -f` quando symlinks estiverem envolvidos para identificar o binário real sendo executado.
  • Em ambientes multiusuário ou em contêineres, `PATH` difere entre usuários e entre contextos `sudo` e não-`sudo` — sempre verifique no contexto correto.
  • O sequestro de PATH através de diretórios graváveis pelo usuário adicionados ao início do `$PATH` é um vetor de ataque real; `which` é uma ferramenta de auditoria rápida de primeira linha contra isso.

Perguntas Frequentes

Qual é a diferença entre `which` e `whereis`?

`which` pesquisa apenas o `$PATH` por executáveis. `whereis` pesquisa um conjunto mais amplo de diretórios de sistema predefinidos para o binário, sua página de manual e seus arquivos de código-fonte simultaneamente. Use `whereis` quando precisar localizar documentação ou código-fonte junto com o binário.

Por que `which cd` não retorna nada?

`cd` é um built-in do shell, não um executável externo. Como `which` só verifica o `$PATH` por arquivos com permissão de execução, ele não consegue encontrar comandos built-in. Use `type cd` em vez disso, que reportará corretamente `cd is a shell builtin`.

O `which` pode me dizer qual versão de um programa está instalada?

Não. `which` retorna apenas o caminho. Para obter a versão, redirecione o resultado: `$(which python3) –version` ou simplesmente `python3 –version`. O caminho do `which` ajuda a confirmar que você está consultando o binário correto.

Por que `which python3` retorna um resultado diferente quando uso `sudo`?

`sudo` executa comandos com o ambiente do root, incluindo o `PATH` do root, que é tipicamente mais restritivo do que o `PATH` de um usuário regular. Diretórios como `~/.local/bin` ou caminhos nvm/pyenv adicionados ao `.bashrc` de um usuário estão ausentes do `PATH` do root. Sempre teste com `sudo which python3` separadamente ao depurar execução com privilégios elevados.

O `which` está disponível no macOS?

Sim, o macOS inclui `which` como parte de seu userland derivado do BSD. No entanto, a versão do macOS não suporta a flag `-a` em todas as versões mais antigas. No macOS moderno com Homebrew, você pode ter o GNU `which` instalado junto com a versão do sistema. Use `type -a which` no macOS para ver qual implementação está ativa.

15%

Poupe 15% em todos os serviços

Teste as suas habilidades e obtenha Desconto em qualquer plano

Utilizar o código:

Skills
Começar a trabalhar