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 frequently move directory trees to other locations or copy their tarballs to other machines, and I would like to have a method to check whether any symlinks in a directory tree A point to locations outside of A since these will be broken in the moved / copied directory.

share|improve this question

4 Answers 4

up vote 3 down vote accepted

You want a program called realpath, used in conjunction with find.

E.g.:

find . -type l -exec realpath {} \; | grep -v "^$(pwd)"
share|improve this answer

GNU coreutils provedes realpath, which resolves symlinks. With this, you could compare each symlink's target to the current working directory with something like:

#!/bin/bash

find . | while read filename
do
  if realpath $filename | grep -E "^$PWD" > /dev/null
  then
    echo 'this file is safe'
  else
    echo 'this file links externally'
  fi
done
share|improve this answer
    
Several problems: no -type l, no -r option to read, IFS not sanitized for read, $filename not quoted, $PWD treated as a regular expression, paths with newline characters not accounted for, /foobar would be matched for $PWD == "/foo" –  Stéphane Chazelas Oct 4 '12 at 21:38

With zsh:

cd -P -- "$dir"
for i (**/*(ND@)) [[ $i:A = $PWD/* ]] || [[ $i:A = $PWD ]] || print -r -- "$i => $i:A"

Now, if the directory is /foo and you have /foo/bar that's a symlink to /foo/baz, that's a link whose target is in /foo, but once moved, the link will still be broken, so you may want also to match symlinks to absolute paths.

But even then, a bar => ../foo/baz in /foo would be an issue (false negative), so would a a => b where b is a symlink outside the tree (false positive, depending on how you want to look at it)

share|improve this answer

Use bindfs to create another view of that directory tree.

mkdir /tmp/view
bindfs /some/directory /tmp/view

Then use the symlinks utility (shipped by many distributions, or compile it from source) to detect cross-filesystem links.

symlinks -r /tmp/view | sed -n 's/^\(absolute\|other_fs\): //p'

(Note that parsing the output assumes that your symbolic links and their targets do not contain newlines, nor do paths to symbolic links contain the substring  -> .) That same utility can also convert absolute symlinks to relative (but you'd want to do that from the original location).

share|improve this answer

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.