I recently found that bash test -e doesn't work with circular symlink.

ln -s ./test ./test
if [[ -e ./test ]]; then echo "exists"; fi
#this won't echo.

so I need to use -L then -e to do it

if [[ -L ./test || -e ./test ]]; then echo "exists"; fi

While this do fix my problem, I started to wonder if there's any other corner cases that -e doesn't cover.

What other corner cases exists? Is there a portable and easy way to reliably detect a file exists?

  • 1
    What is a circular symlink? Is test a directory – daisy Mar 6 '17 at 3:03
  • 1
    @daisy Suppose test does not exist, then ln -s ./test test. This is a symbolic link that points to itself. This doesn't seem very useful to me, but that's what a circular symbolic link is – Fox Mar 6 '17 at 3:09
  • And -f is insufficient ? – Jeff Schaller Mar 6 '17 at 3:18
  • 1
    What is your use case? stat file >/dev/null 2>&1 exits with failure if the file does not exist or some directory on the path to file lacks execute permission (lacking read is okay!), and success in all (?) other cases, whether file is a file, symlink, directory, etc. – Fox Mar 6 '17 at 3:58
  • You can try ls -d ./test &>/dev/null && echo "exists" – user218374 Mar 6 '17 at 11:23

The problem isn't with the circular link, it's the symlink pointing to a file that doesn't exist. The same thing will happen any time you point a symlink to any file that doesn't exist.

From the test man page:

If file is a symbolic link, test will fully dereference it and then evaluate the expression against the file referenced, except for the -h and -L primaries.

This is the only edge case for test mentioned in its man page.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.