realpath e readlink: Resolvendo Caminhos Absolutos e Symlinks

realpath e readlink: Resolvendo Caminhos Absolutos e Symlinks

O Que Voce Vai Aprender

  • A diferenca entre realpath e readlink, e quando usar cada um
  • Como resolver symlinks e segmentos .. em um caminho absoluto
  • Os tres niveis de verificacao de existencia por tras de -f / -e / -m
  • Como escrever resolucao segura de caminhos em shell scripts

Resumo Rapido

  • Quer um caminho absoluto --> realpath path
  • Quer ver para onde um symlink aponta --> readlink link
  • Quer seguir cada link e .. ate um unico 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 padrao a partir do coreutils 8.15
  • Comportamento neste artigo verificado no coreutils 9.4

Qual e a diferenca entre realpath e readlink?

Conclusao: readlink le o conteudo 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 sao proximos em nome e proposito, mas seu comportamento basico difere.

Aspecto readlink (sem opcoes) realpath (sem opcoes)
Proposito principal Ler a string de destino do link Calcular o caminho absoluto real
Alvo nao e um symlink Nao imprime nada, falha Retorna o caminho absoluto
Destino do link e relativo Mantido como a string relativa armazenada Resolvido para caminho absoluto
Resolucao de .. Nao Sim

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

Conclusao: 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 e um link relativo para usr/bin.

$ readlink /bin
usr/bin

Como o valor armazenado e relativo (usr/bin), a saida permanece relativa, e .. nao e 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 familia -f tem tres modos que diferem em quao rigorosa e a verificacao de existencia.

Opcao Forma longa Requisito de existencia
-f --canonicalize Todos exceto o ultimo 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 voce esta 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. Substituicao de comando $(...) ja remove quebras de linha finais, entao raramente e necessario la, mas ajuda ao concatenar com printf.

Como usar realpath?

Conclusao: realpath path retorna o caminho absoluto com todos os symlinks, .. e . resolvidos. Seu padrao corresponde a readlink -f: todos exceto o ultimo componente devem existir.

$ realpath /bin
/usr/bin

Diferente de readlink, realpath tambem funciona em caminhos que nao sao symlinks -- essa e a grande diferenca pratica.

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

.., . e barras duplicadas sao todos normalizados.

Controlar a verificacao de existencia (-e / -m)

realpath usa os mesmos tres niveis que readlink.

  • Padrao: todos exceto o ultimo 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

Alem de caminhos absolutos, realpath tambem pode calcular um caminho relativo a um diretorio base.

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

Util em scripts que precisam de uma posicao relativa a um diretorio de configuracao. --relative-base=DIR mantem o resultado relativo apenas quando o alvo esta sob DIR, e absoluto caso contrario.

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 sao as armadilhas comuns?

Conclusao: A maior armadilha e que readlink sozinho falha silenciosamente em arquivos regulares. Para resolucao de caminhos em scripts, use realpath ou readlink -f.

readlink (sem opcoes) nao imprime nada e retorna exit 1 para qualquer coisa que nao seja um symlink.

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

Escrito em um script, isso deixa uma variavel vazia quando o alvo nao e um symlink -- uma forma facil 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 voce quer resolver um caminho de saida que ainda nao existe, -e vai falhar. Para um caminho que voce esta prestes a criar, escolha -f (ultimo componente pode estar ausente) ou -m (tudo pode estar ausente).

Uma barra final / em um symlink aponta para o diretorio que ele referencia, nao para o link em si. Isso pode mudar silenciosamente o resultado resolvido, entao omita a barra final / quando quiser inspecionar o link em si.

Regra pratica

  • Ver a string de destino um nivel --> readlink link
  • Precisa do caminho absoluto real (scripts incluidos) --> realpath path ou readlink -f path
  • Garantir existencia --> -e
  • Calcular um caminho que voce vai criar --> -f ou -m

Um exemplo pratico em script

Conclusao: Resolver o diretorio real de instalacao de um script e o caso de uso classico para realpath / readlink -f. Mesmo quando iniciado atraves de um symlink, voce obtem o diretorio real.

Shell scripts frequentemente precisam referenciar outros arquivos relativos a sua propria localizacao. realpath resolve a localizacao real mesmo quando o script e invocado atraves 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 minimos sem realpath, readlink -f "$0" e a alternativa direta. Ambos usam por padrao o mesmo comportamento "todos exceto o ultimo componente devem existir".

Sistemas baseados em BSD como macOS vem com um readlink sem -f (ou com comportamento diferente). Para scripts portaveis que nao podem assumir GNU coreutils, verifique se realpath existe, ou use o idioma cd "$(dirname "$0")" && pwd como fallback.

Proximas Leituras