Não tenho conhecimento de tal utilidade. No entanto, sua abordagem é falha (e eu concordo que é muito difícil acertar).
O modificador :a
calcula um caminho absoluto sem nenhum acesso ao sistema de arquivos. Em particular, ele altera a/b/..
para a
, independentemente de o a/b
ser um link simbólico ou não.
Se você tiver um link simbólico /a/b -> ../foo
, isso será /foo
somente se /a
não for um link simbólico em si. Mesmo que você canonicize o $(dirname $1)
, isso ainda não funcionaria para links simbólicos como /a/b -> x/../../foo
if x
em si é um symlink.
No seu caso:
/tmp/example/A/B/C/D/symlink-0 -> ../../symlink-1/b/c/d/target
resolve /tmp/example/A/B/symlink-1/b/c/d/target
apenas porque nem /tmp/example/A/B/C/D
nem /tmp/example/A/B/C
são links simbólicos.
Em outras palavras, para obter um caminho absoluto para o destino de um link simbólico livre de ..
componentes, talvez seja necessário resolver mais de um link simbólico e não é possível fazê-lo sozinho combinando o caminho do arquivo e o alvo do link simbólico.
Se você quiser esse caminho, a maneira mais fácil (e eu diria apenas razoável e / ou útil) é pegar o caminho canônico daquele destino do link simbólico, que é onde todos os componentes do caminho não são ..
, .
nem links simbólicos, exceto possivelmente para o último. Para isso, você poderia fazer:
zmodload -F zsh/stat b:zstat
canonicalize1() {
if [ -L "$1" ]; then
local link
zstat -A link +link -- "$1" || return
case $link in
(/*) ;;
(*)
case $1:h in
(*/) link=$1:h$link;;
(*) link=$1:h/$link;;
esac;;
esac
printf '%s\n' $link:h:A/$link:t
else
printf '%s\n' $1:A
fi
}
Em seus links simbólicos /tmp/example/A/B/C/D/symlink-0
, isso ainda dá /tmp/example/a/b/c/d/target
, já que o alvo do link simbólico não é um link simbólico, mas se não é isso que você quer, então eu pergunto: qual resultado você quer ao fazer:
canonicalize1 /tmp/x/y
Onde /tmp/x/y
é um link simbólico para ../foo
e /tmp/x
um link simbólico para /a/b/c
e /a
, /a/b
, /a/b/c
também são eles próprios links simbólicos?