Skip to main content

Path Resolution and Symlinks

Understanding how find handles paths is critical, especially when passing the output to other scripts or when navigating complex directory structures containing symbolic links (symlinks).

Absolute vs. Relative Paths

find is fundamentally literal. The way it formats its output depends entirely on how you define the starting path.

If you start the search with a relative path (like . or ./dir), the output will be relative.

$ find . -name "test.txt"
./projects/test.txt

$ find projects -name "test.txt"
projects/test.txt

If you start the search with an absolute path (starting with /), the output will be absolute. This is heavily preferred in production scripts to avoid dependency on the current working directory.

$ find /home/user/projects -name "test.txt"
/home/user/projects/test.txt

By default, find does not follow symbolic links. If it encounters a symlink that points to a directory, it will report the symlink itself, but it will not enter the directory to search its contents.

You can alter this behavior using three specific flags: -P, -L, and -H. These flags must be placed immediately after the find command, before the path.

1. The -P Flag (Default Behavior)

Never follow symbolic links. This is the safest and default mode.

find -P /var/www -name "*.html"

Follow symbolic links. If find encounters a symlink to a directory, it will resolve the link and traverse into the target directory.

find -L /var/www -name "*.html"

Warning: Using -L can cause infinite loops if symlinks point back to parent directories. GNU find has built-in loop detection and will print a warning if it encounters one, but it is still a performance risk.

Do not follow symbolic links during the search, EXCEPT if the starting path provided on the command line is itself a symlink.

# If /opt/app is a symlink to /var/local/app
find -H /opt/app -name "*.conf"

In this scenario, find will resolve /opt/app and search inside /var/local/app. However, if it finds other symlinks inside that directory, it will not follow them.

When you follow symlinks (e.g., using -L), the behavior of tests like -type and -mtime changes:

  • Without -L: -type l matches symlinks. -type d does not match a symlink to a directory.
  • With -L: find tests the properties of the target file, not the link itself. -type l will always be false (unless the link is broken), and -type d will match a symlink pointing to a directory.

A common administrative task is finding symlinks that point to deleted or moved files.

# Find all links (-type l) that point to non-existent targets (-xtype l)
find /path -type l -xtype l

(The -xtype test is a GNU extension that checks the type of the file the symlink points to. If it returns l even when checking the target, it implies the link is broken).