I want to determine all broken symlinks within a directory.

In ignorance of a better solution, I tried this simple bash one-liner (bash version is 4.2.46, which may be worth mentioning because it's a bit dated):

for f in $(ls); do test -L "$f" || continue; test -e "$f" || echo "$f deadlink"; done

Unfortunately this does not work. I tried nailing down the error and if I run this

for f in $(ls); do test -L $f && echo "$f is a valid symlink"; done

no output is produced, despite existing and valid symlinks. If I run the same command with $f replaced with the actual file name, it works. Also f=filename; test -L $f && echo "$f is a valid symlink"; works as expected, so the problem seems to be the loop.

What am I missing?


1 Answer 1


I suspect the problem comes from ls’s use of colours in its output. Since you’re parsing ls’s output, if ls outputs colours, the corresponding escape codes will end up in the values given to f, and test will fail to find a matching file. Since test fails the test without any output in such cases, you wouldn’t be any the wiser.

Use a glob instead:

for f in *; do test -L "$f" || continue; test -e "$f" || echo "$f deadlink"; done

See How can I find broken symlinks for other possible solutions to your underlying problem.

  • Indeed the colors are a problem. If I replace $(ls) with $(ls --color=never), it works as well (alternatively: $(\ls) to avoid alias expansion). Thanks for the idea of using a simple glob as well. Question answered.
    – andreee
    Mar 3, 2023 at 12:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .