Re: :a modifier resolves symlinks - docs say it shouldn't

Mikael Magnusson <[email protected]>
Newsgroups gmane.comp.shells.zsh.devel
Message-ID <CAHYJk3S0s_KR6hSEmu36d_n+FFr7d4-WCtvBvhDxyNoYiKMPcA@mail.gmail.com>
On Sat, May 30, 2026 at 5:13 AM Langbart <[email protected]> wrote:
>
> Guten Tag,
>
> the :a modifier doc claims it operates on the logical path, but testing when CWD
> is a symlink says otherwise.
>
> ```txt
> man zshexpn | grep -C9 'not the physical directory'
>        modifiers also work on the result of filename generation and parameter
>        expansion, except where noted.
>
>        a      Turn a file name into an absolute path:  prepends the current
>               directory, if necessary; remove `.' path segments; and remove
>               `..' path segments and the segments that immediately precede
>               them.
>
>               This transformation is agnostic about what is in the filesystem,
>               i.e. is on the logical, not the physical directory.  It takes
>               place in the same manner as when changing directories when
>               neither of the options CHASE_DOTS or CHASE_LINKS is set.  For
>               example, `/before/here/../after' is always transformed to
>               `/before/after', regardless of whether `/before/here' exists or
>               what kind of object (dir, file, symlink, etc.) it is.
>
>        A      Turn a file name into an absolute path as the `a' modifier does,
>               and then pass the result through the realpath(3) library
>               function to resolve symbolic links.
> ```
>
> To reproduce:
>
> `test.zsh` script
>
> ```zsh
> #!/usr/bin/env zsh --no-rcs
>
> tmp_dir=$(mktemp -d)
> {
>   mkdir -p ${tmp_dir}/real
>   ln -s ${tmp_dir}/real ${tmp_dir}/link
>   cd ${tmp_dir}/link
>   dir=x
>
>   echo "PWD     ${PWD}"
>   echo "pwd -L  $(pwd -L)"
>   echo "pwd -P  $(pwd -P)"
>   echo
>   echo ":a      ${dir:a}"
>   echo ":A      ${dir:A}"
>   echo ":P      ${dir:P}"
> } always {
>   rm -rf ${tmp_dir}
> }
> ```
>
> Expected for ':a':  /tmp/.../link/x
>
> Actual   for ':a':  /tmp/.../real/x
>
> ```zsh
> podman run --quiet --rm -v $PWD/test.zsh:/test.zsh:ro alpine sh -c '
> apk add --quiet zsh
> zsh /test.zsh'
>
> PWD     /tmp/tmp.JcNaha/link
> pwd -L  /tmp/tmp.JcNaha/link
> pwd -P  /tmp/tmp.JcNaha/real
>
> :a      /tmp/tmp.JcNaha/real/x
> :A      /tmp/tmp.JcNaha/real/x
> :P      /tmp/tmp.JcNaha/real/x
> ```
>
> The issue came up in a bug report: https://github.com/junegunn/fzf/issues/4816
>
> P.S. I also ran it on macOS (15.7.7) with a very recent zsh dev version; the
> issue persists (ZSH_PATCHLEVEL zsh-5.9.0.2-test-325-ga58ad1a).

This is exactly what the documentation says will happen. You gave "x"
to the :a modifier so the current directory (/tmp/tmp.JcNaha/real) is
prepended, then that has no relative segments and we are done. Note
that if you change dir to ${tmp_dir}/link/x then the output is:
:a      /tmp/tmp.XUdbboXIdJ/link/x
:A      /tmp/tmp.XUdbboXIdJ/real/x
:P      /tmp/tmp.XUdbboXIdJ/real/x

I suppose you may expect it to prepend $PWD rather than the current
directory for relative paths, but that is not the case.

-- 
Mikael Magnusson
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.