1

I am collecting all the files under a directory. But this directory has symlinks to other directory outside of the directory where I am running the find command and it contains huge number of files as well as directories. Though I can ignore this directory with the help of prune, the problem arises when a symlinks point to a child directory of this huge directory. I want to ignore all the symlinks which points to any on the child directories.

Here is a sample command find -L /usr/local/searchdir

Few symlinks

/usr/local/searchdir/d0/link --> /small/dir  
/usr/local/searchdir/d1/file.o  
/usr/local/searchdir/d2/link --> /little/dir  
/usr/local/searchdir/d3/link --> /hugedir  
/usr/local/searchdir/d4/link --> /hugedir/main  
.  
.  
.  
/usr/local/searchdir/dx      --> /hugedir/c4  

Problematic directories

/hugedir/c1/tmp  
/hugedir/c2/main  
/hugedir/c3/dir  
/hugedir/c4/ext  
/hugedir/c5/client  
/hugedir/c6/bin  
/hugedir/c7/std
  • Please can you show what you tried with -prune? – JigglyNaga Sep 15 '16 at 9:53
  • Here is the command find -L /usr/local/searchdir -name hugedir -prune -o -type f -printf "::%p::,%s,%T@\n" – Rakesh Sep 15 '16 at 13:08
  • As you can see the search directory /usr/local/searchdir has symlinks pointing to sub directories of /hugedir, so the command is not able to prune the contents from these child directories because path doesn't have hugedir in the pathname. For eg. /usr/local/searchdir/d2/link/little/dir is not pruned though it lies under /hugedir. – Rakesh Sep 15 '16 at 13:13
1

GNU find has a -lname option to match on the target of a symlink but it can't be used with -L/-follow.

Assuming you do want to use -L, you'd need to call -exec to implement your own check that the link is on that large dir.

Here using GNU find's -xtype as an optimisation as assuming your system has a readlink and that it supports the -f option a la GNU readlink:

find -L . -type d -xtype l -exec sh -c '
  case $(readlink -f "$1") in
    (/hugedir | /hugedir/*) exit 0;;
    (*) exit 1;;
  esac' sh {} \; -prune -o ...

Or slightly more efficient.

find -L . -type d -xtype l -exec sh -c '
  cd -P "$1" && case $PWD in
    (/hugedir | /hugedir/*) exit 0;;
    (*) exit 1;;
  esac' sh {} \; -prune -o ...
  • +1 Nice one Stéphane, especially the use of $1 in compbination with -exec and {}. However had you not better make use of -execdir ? – Cbhihe Sep 16 '16 at 14:24
  • 1
    @Cbhihe, with -execdir cmd, cmd's current working directory would be the directory that contains the symlink, so you'd still need to do a cd -P (even cd -P -- with FreeBSD find, though FreeBSD find doesn't have the -printf that the OP is using). With -L, -execdir doesn't really add the security benefit that it does when not using -L. – Stéphane Chazelas Sep 16 '16 at 14:28
0

The find command by default does ignore symlinks. You can anyway specify explicitly this behaviour via the -P flag:

   -P     Never follow symbolic links.  This is the default behaviour.  When find examines or prints information a file, and the file is a symbolic link, the information used shall be  taken  from  the
          properties of the symbolic link itself.

   -L     Follow  symbolic  links.  When find examines or prints information about files, the information used shall be taken from the properties of the file to which the link points, not from the link
          itself (unless it is a broken symbolic link or find is unable to examine the file to which the link points).  Use of this option implies -noleaf.  If you later use the -P option, -noleaf will
          still be in effect.  If -L is in effect and find discovers a symbolic link to a subdirectory during its search, the subdirectory pointed to by the symbolic link will be searched.

          When  the  -L  option  is in effect, the -type predicate will always match against the type of the file that a symbolic link points to rather than the link itself (unless the symbolic link is
          broken).  Using -L causes the -lname and -ilname predicates always to return false.

   -H     Do not follow symbolic links, except while processing the command line arguments.  When find examines or prints information about files, the information used shall be taken from  the  proper‐
          ties  of  the  symbolic link itself.   The only exception to this behaviour is when a file specified on the command line is a symbolic link, and the link can be resolved.  For that situation,
          the information used is taken from whatever the link points to (that is, the link is followed).  The information about the link itself is used as a fallback if the file pointed to by the sym‐
          bolic  link  cannot  be  examined.   If  -H  is in effect and one of the paths specified on the command line is a symbolic link to a directory, the contents of that directory will be examined
          (though of course -maxdepth 0 would prevent this).
  • I have -L added in the command as I need to follow symlinks but I don't want to follow them when they are pointing to any of the children directories of a special directory. Since there are many symlinks pointing to children of this special directory, it is very difficult exclude or prune them with any pattern. – Rakesh Sep 15 '16 at 9:16

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.