Domine o Comando `which` no Linux: Encontre o Binário Correto!

O comando `which` no Linux é uma ferramenta que identifica o arquivo executável que é acionado quando você insere um comando no terminal. Em situações onde existem diversas versões de um mesmo programa no seu sistema, o `which` se torna indispensável para determinar qual delas o shell irá utilizar.

Arquivos Binários e seus Caminhos

Ao executar um programa ou comando no terminal, o shell (comumente o Bash em distribuições modernas) precisa localizar e iniciar esse comando. Alguns comandos, como `cd`, `history` e `pwd`, são internos ao shell, facilitando sua localização.

Mas como o Bash encontra outros comandos, programas e binários externos? Ele utiliza o “path” (caminho), que é, na verdade, um conjunto de caminhos, cada um apontando para um diretório. O Bash procura em cada um desses diretórios por um executável que corresponda ao comando que você digitou. Ao encontrar uma correspondência, ele executa o programa e interrompe a busca.

Você pode visualizar os diretórios no seu path usando o comando `echo` e a variável de ambiente `$PATH`. Digite o seguinte no terminal e pressione Enter:

echo $PATH

A saída será uma lista de diretórios, separados por dois pontos (:). Em um sistema típico, o Bash pesquisará os seguintes diretórios nesta ordem:

/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/user/games
/usr/local/games
/snap/bin

A existência de várias pastas `/sbin` e `/bin` no sistema de arquivos pode gerar confusão.

Analisando os Caminhos

Suponha que temos uma versão atualizada de um programa chamado `htg` em nosso diretório atual. Podemos executá-lo com o comando:

./htg

Este programa simplesmente exibe o número da versão (1.2.138) e finaliza. Para executar um programa no diretório atual, é preciso usar “./” antes do nome, indicando ao Bash onde encontrá-lo.

Para executar este programa de qualquer diretório, vamos movê-lo para `/usr/bin`. Assim, o Bash o encontrará no path e o executará. Não precisaremos mais do executável no diretório atual, nem do “./” antes do nome:

sudo mv htg /usr/bin

Agora, tentemos executar o programa com o comando:

htg

Algo foi executado, mas não é a nova versão. É a versão antiga, 1.2.105.

O Comando `which`

O comando `which` foi desenvolvido para resolver problemas como o demonstrado acima. Para verificar qual versão do `htg` está sendo executada, usaremos o seguinte comando:

which htg

O `which` nos informa que a versão do `htg` encontrada está no diretório `/usr/local/bin`. Este diretório aparece no path antes de `/usr/bin`, onde colocamos a versão mais nova. Por isso, o Bash está executando a versão mais antiga.

Usando a opção `-a` (todos), o `which` continua a busca mesmo após encontrar uma correspondência:

which -a htg

Agora, o comando lista todas as correspondências encontradas no path.

O problema é que existe uma versão antiga do programa em um diretório que aparece antes do diretório com a nova versão no path. Para confirmar, podemos executar as duas versões explicitamente:

/usr/local/bin/htg
/usr/bin/htg

A solução é simples: remover a versão antiga de `/usr/local/bin` ou mover a nova versão de `/usr/bin` para `/usr/local/bin`.

Resultados Enganosos

Nem sempre dois resultados significam dois arquivos binários distintos.

Vamos usar o comando `which` com a opção `-a` para verificar as versões do programa `less`:

which -a less

O comando indica dois locais com uma versão do programa `less`. No entanto, não seria comum ter duas versões diferentes do `less` (ou a mesma versão em vários locais). Vamos investigar mais a fundo.

Usando as opções `ls -lh`, podemos analisar o que está acontecendo:

ls -lh /usr/bin/less

O tamanho do arquivo é de apenas nove bytes! Definitivamente não é uma cópia completa do `less`. O primeiro caractere da listagem é um “l”, indicando que se trata de um link simbólico (como um atalho). Este link aponta para a cópia do `less` em `/bin`.

Analisando a versão do `less` em `/bin`:

ls -lh /bin/less

Esta entrada é um arquivo binário real. O primeiro caractere da listagem é um “-“, indicando que é um arquivo normal e o tamanho é 167 KB. Portanto, existe apenas uma cópia do `less` instalada. O outro local é apenas um link simbólico.

Verificando Múltiplos Comandos

O comando `which` pode verificar vários programas e comandos ao mesmo tempo, listando o resultado de cada um na ordem em que foram fornecidos:

which ping cat uptime date head

Qual é o Caminho do `which`?

Você pode até mesmo usar o comando `which` para verificar seu próprio caminho digitando:

which which

Além da curiosidade, o comando `which` é mais útil quando você espera um comportamento específico de um comando ou programa, mas obtém outro. Nesses casos, você pode verificar se o comando que o Bash está executando é o que você pretendia usar.