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