realpath e readlink: Resolvendo Caminhos Absolutos e Symlinks

realpath e readlink: Resolvendo Caminhos Absolutos e Symlinks

O Que Você Vai Aprender

  • A diferença entre realpath e readlink, e quando usar cada um
  • Como resolver symlinks e segmentos .. em um caminho absoluto
  • Os três níveis de verificação de existência por trás de -f / -e / -m
  • Como escrever resolução segura de caminhos em shell scripts

Resumo Rápido

  • Quer um caminho absoluto --> realpath path
  • Quer ver para onde um symlink aponta --> readlink link
  • Quer seguir cada link e .. até um único caminho real --> realpath path ou readlink -f path
  • Em scripts, use realpath ou readlink -f -- nunca readlink sozinho

Premissas (ambiente alvo)

  • GNU coreutils (Ubuntu / Debian / RHEL e a maioria das distros Linux comuns)
  • realpath vem como padrão a partir do coreutils 8.15
  • Comportamento neste artigo verificado no coreutils 9.4

Qual é a diferença entre realpath e readlink?

Conclusão: readlink lê o conteúdo de um symlink (sua string de destino). realpath resolve um caminho inteiro em sua forma absoluta real. Adicione readlink -f e ele se comporta quase exatamente como realpath.

Os dois são próximos em nome e propósito, mas seu comportamento básico difere.

Aspecto readlink (sem opções) realpath (sem opções)
Propósito principal Ler a string de destino do link Calcular o caminho absoluto real
Alvo não é um symlink Não imprime nada, falha Retorna o caminho absoluto
Destino do link é relativo Mantido como a string relativa armazenada Resolvido para caminho absoluto
Resolução de .. Não Sim

O ponto principal: readlink sozinho é apenas para symlinks. Execute em um arquivo regular ou diretório e ele falha silenciosamente (veja armadilhas abaixo). realpath, por outro lado, retorna um caminho absoluto para qualquer caminho.

Conclusão: readlink sozinho imprime o destino do link como armazenado. Adicione -f e ele segue links recursivamente e retorna o caminho absoluto final.

readlink imprime a string armazenada dentro de um symlink. Na maioria dos sistemas, /bin é um link relativo para usr/bin.

$ readlink /bin
usr/bin

Como o valor armazenado é relativo (usr/bin), a saída permanece relativa, e .. não é resolvido. Use isso quando quiser apenas saber para onde um link aponta.

Resolver completamente com -f / -e / -m

Adicione -f (--canonicalize) para seguir cada symlink no caminho, processar .. e retornar um caminho absoluto.

$ readlink -f /bin
/usr/bin

A família -f tem três modos que diferem em quão rigorosa é a verificação de existência.

Opção Forma longa Requisito de existência
-f --canonicalize Todos exceto o último componente devem existir
-e --canonicalize-existing Todos os componentes devem existir
-m --canonicalize-missing Nenhum precisa existir
# Pai existe, apenas o arquivo final esta ausente --> -f funciona, -e falha
$ readlink -f /etc/does-not-exist.conf
/etc/does-not-exist.conf

$ readlink -e /etc/does-not-exist.conf
# nao imprime nada, exit 1

Use -f ou -m para calcular o caminho final de um arquivo que você está prestes a criar; use -e quando precisar garantir que o caminho existe.

Ao mostrar o destino de um link, -n (--no-newline) suprime a quebra de linha final. Substituição de comando $(...) já remove quebras de linha finais, então raramente é necessário lá, mas ajuda ao concatenar com printf.

Como usar realpath?

Conclusão: realpath path retorna o caminho absoluto com todos os symlinks, .. e . resolvidos. Seu padrão corresponde a readlink -f: todos exceto o último componente devem existir.

$ realpath /bin
/usr/bin

Diferente de readlink, realpath também funciona em caminhos que não são symlinks -- essa é a grande diferença prática.

$ cd /var/log
$ realpath ../tmp
/var/tmp

.., . e barras duplicadas são todos normalizados.

Controlar a verificação de existência (-e / -m)

realpath usa os mesmos três níveis que readlink.

  • Padrão: todos exceto o último componente devem existir (o pai deve ser real)
  • -e (--canonicalize-existing): cada componente deve existir
  • -m (--canonicalize-missing): nenhum componente precisa existir
# Diretorio pai nao existe --> falha mesmo por padrao
$ realpath /no-such-dir/file.txt
realpath: /no-such-dir/file.txt: No such file or directory

# -m normaliza e retorna mesmo um caminho totalmente ausente
$ realpath -m /no-such-dir/file.txt
/no-such-dir/file.txt

Converter para caminho relativo com --relative-to

Além de caminhos absolutos, realpath também pode calcular um caminho relativo a um diretório base.

$ realpath --relative-to=/home /home/alice/work/report.txt
alice/work/report.txt

Útil em scripts que precisam de uma posição relativa a um diretório de configuração. --relative-base=DIR mantém o resultado relativo apenas quando o alvo está sob DIR, e absoluto caso contrário.

Adicione -s (--strip / --no-symlinks) para normalizar . e .. sem resolver symlinks. Use quando quiser organizar um caminho preservando a estrutura de links.

$ realpath -s /bin/../bin
/bin

Quais são as armadilhas comuns?

Conclusão: A maior armadilha é que readlink sozinho falha silenciosamente em arquivos regulares. Para resolução de caminhos em scripts, use realpath ou readlink -f.

readlink (sem opções) não imprime nada e retorna exit 1 para qualquer coisa que não seja um symlink.

$ readlink /etc/hostname
# sem saida, exit 1 (/etc/hostname e um arquivo regular)

Escrito em um script, isso deixa uma variável vazia quando o alvo não é um symlink -- uma forma fácil de causar surpresas.

# Arriscado: p fica vazio se $f nao for um symlink
p=$(readlink "$f")

# Seguro: p contem um caminho absoluto para symlinks e arquivos regulares
p=$(realpath "$f")

2. Confundir -f e -e

Se você quer resolver um caminho de saída que ainda não existe, -e vai falhar. Para um caminho que você está prestes a criar, escolha -f (último componente pode estar ausente) ou -m (tudo pode estar ausente).

Uma barra final / em um symlink aponta para o diretório que ele referência, não para o link em si. Isso pode mudar silenciosamente o resultado resolvido, então omita a barra final / quando quiser inspecionar o link em si.

Regra prática

  • Ver a string de destino um nível --> readlink link
  • Precisa do caminho absoluto real (scripts incluídos) --> realpath path ou readlink -f path
  • Garantir existência --> -e
  • Calcular um caminho que você vai criar --> -f ou -m

Um exemplo prático em script

Conclusão: Resolver o diretório real de instalação de um script é o caso de uso clássico para realpath / readlink -f. Mesmo quando iniciado através de um symlink, você obtém o diretório real.

Shell scripts frequentemente precisam referenciar outros arquivos relativos a sua própria localização. realpath resolve a localização real mesmo quando o script é invocado através de um symlink.

#!/bin/bash
# Resolve the script's real directory
script_path=$(realpath "$0")
script_dir=$(dirname "$script_path")

echo "Running script: $script_path"
echo "Install dir:    $script_dir"

# Safely reference a config file next to the script
config="$script_dir/config.env"

Em sistemas mínimos sem realpath, readlink -f "$0" é a alternativa direta. Ambos usam por padrão o mesmo comportamento "todos exceto o último componente devem existir".

Sistemas baseados em BSD como macOS vêm com um readlink sem -f (ou com comportamento diferente). Para scripts portáveis que não podem assumir GNU coreutils, verifique se realpath existe, ou use o idioma cd "$(dirname "$0")" && pwd como fallback.

Próximas Leituras