Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I usually do a find with an environment variable as the path when searching for source code. Recently I replaced my environment variable with a symbolic link, and it broke Bash's shell completion. When I do a find using the symlink it doesn't work, but if I use the actual path that the symlink points to, it works find.

ln -s /some/source/dir /the/source
export SYMLINK=/the/source
export DIR=/some/source/dir

find $SYMLINK -name file.c        // doesn't find anything
find $DIR -name file.c            // works as expected

In this example $SYMLINK is a symbolic link for $DIR's value.

So, why does bash handle symlink environment variables differently?

share|improve this question

2 Answers 2

up vote 5 down vote accepted

It's not bash, it's find; though you'll find that most utilities will follow the same principle:

  • If operating on file contents, a symlink to a regular file is equivalent to the actual file.
  • If operating on directory entries, symlinks are a category of their own.

When you run find $SYMLINK, find sees an object that isn't a directory, so it doesn't traverse it. If you want to treat a symlink to a directory as if it was that directory, add a / at the end (a few broken systems or commands may require "$SYMLINK/."):

find "$SYMLINK/" -name file.c

For find, you can also use the -H option, which tells it to treat any symlink on the command line as if you had specified the target:

find -H "$SYMLINK" -name file.c
share|improve this answer

It's not bash, it's find. Following symlinks in a recursive directory traversal often leads to infinite loops (consider the common trick of ln -s foo . to provide a compatibility path). POSIX find includes the -follow predicate to override this; perhaps more usefully in this case, GNU find provides -H to follow only symlinks directly specified as parameters, while continuing to avoid expanding symlinks found during traversal. You could use these with an alias:

alias find='find -H'
share|improve this answer
1  
For -follow and -H, it's the opposite: -H is POSIX, -follow is a GNU (and other) extension. –  Gilles Jun 3 '11 at 16:26
    
@Gilles: huh, I admit to not checking the POSIX standard specifically but -follow predates POSIX. –  geekosaur Jun 3 '11 at 16:28

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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