My OS and home directory are on an SSD. I store some large files on a hard disk, and symlink from my home directory to the hard disk (eg. ~/Videos/Films is a symlink to /mnt/hdd/Films). I also have a number of Wine prefixes, each of which has dosdevices/z: symlinked to /.

So, if I used find without -L, it will miss everything that's on the hard disk. But if I use find with -L, it ends up in a loop due to Wine's symlink to /.

Is there any sensible way of resolving this, so that find searches where I want it to? Intuitively, I'm wanting something along the lines of "follow symlinks, unless they're under a directory called dosdevices". "Follow symlinks that are to something on the hard disk" would work too.

4 Answers 4


The -prune primary tells find not to recurse under a directory.

find -L -path ~/.wine/dosdevices -prune -o -type f -name 'My Favorite Movie.*' -print

If you want to use -lname in your condition, you can't use the -L option, because -L causes most predicates to act on the target of the link, including -lname. My recommendation in that case would be to use both your home directory and the hard disk root as the roots of your search.

find ~ /mnt/hdd -xtype f -name 'My Favorite Movie.*'

You might run find ~ -type l … to gather a list of symbolic links and use them as additional roots.

( IFS=$'\n'; set -f;
  find ~ $(find ~ -type l -lname '/mnt/hdd/*') \
       -xtype f -name 'My Favorite Movie.*' )

If you really want to recurse under symbolic links, you can exclude specific symbolic links by target instead of by name. However you can only exclude a finite list, not a pattern or subtree this way.

find -L \( -samefile /exclude/this -o -samefile ~/and/that \) -prune -o \
     -type f -name 'My Favorite Movie.*' -print

You can use other criteria such as ! -writable (files that you don't have write permission to), but I don't think GNU find has a way to recurse under symbolic links only if their target text matches a certain expression.

You could build a find command that does almost what you want except for not excluding enough symbolic links, run find2perl to convert the query to a Perl script, and tweak the Perl script a bit. There are many switches of GNU find that find2perl doesn't recognize, however.

  • Thanks! -prune is just the sort of thing I was looking for. I've found that find ~ \( -lname ~ -o -lname ~/\* -o -lname / \) -xtype d lists all the symlinks that I don't want to follow; I'm now trying to find a way to use that query to prune. Jan 1, 2014 at 11:00
  • @MarkRaymond The general principle is find ~ <negative criteria> -prune -o <positive criteria> -print, so find ~ \( -lname ~ -o -lname ~/\* -o -lname / \) -xtype d -prune -o <whatever it is you want> -print Jan 1, 2014 at 15:09
  • @Giles - that works fine without -L, but once I add -L, the -lname expressions don't work any more (as the man page says they won't). So basically I then need some conditions to follow symlinks and others not to! Jan 1, 2014 at 15:50
  • I can't think of a way of doing exactly what you want with find. See my edit for some approximations. Jan 1, 2014 at 16:21

To search ALL links, this worked for me:

find -L . -name \*.txt

How many symlinks to hard disks do you have? If it is not too many one solution is to not use "-L" while explicitly specifying the symlinks that you do want to follow on the find command line. Something like:

find .  ~/Videos/Films -name '*file I want*' ...

This will search the current directory (".") as well as the symlink "~/Videos/Films" but will not descend into other symlinks.


Another solution that side-steps the issue (at least for my case) is to use bind mounts instead of symbolic links for the directories on the hard disk. This is done by adding entries in /etc/fstab like this:

/mnt/hdd/Films /home/mark/Videos/Films none bind 0 0

You must log in to answer this question.

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