Let $foo and $bar be two absolute directory names (output by realpath). I want to test if either is contained in the other one, at any depth, and execute commands accordingly.

I thought I'd use find, but its exit status doesn't tell whether something has been found or not. So I've come to:

if [ x$(find -H "$foo" -path "$bar" -printf y -quit) == xy \
    -o x$(find -H "$bar" -path "$foo" -printf y -quit) == xy ] ; then

Is it correct? Is there something simpler?

Context: my home dir contains an encrypted folder (ecryptfs). I'm writing a script that will sync its argument to the cloud. I don't want the decrypted files to be synced, so I'll test whether the argument overlaps the encrypted folder to unmount the ecryptfs before syncing.

  • I don't understand. When you have 2 full (realpath) paths they can't contain eachother as they are absolute. Do you mean: Share a common parent folder? – Johan Jan 8 '19 at 9:49
  • What are you looking for?: a tree being a sub-tree of another?; a tree being a sub-tree of another, but having a different name, because of sys-links?; a tree having a copy of part of another tree?; a tree containing a part of another tree because of bind mounts etc?; something else? – ctrl-alt-delor Jan 8 '19 at 10:06
  • Can't you just ignore the mounted directory with your script? How does the script sync the files? – Kusalananda Jan 8 '19 at 10:20
  • @Johan I'm searching if either is contained in the other one (it could be foo under bar or bar under foo) – L. Levrel Jan 8 '19 at 16:10
  • @ctrl-alt-delor a tree being a sub-tree of another – L. Levrel Jan 8 '19 at 16:10

I'm not sure I fully understand the question and the context. But maybe this works:

foo="$(realpath "...")"
bar="$(realpath "...")"

if [[ $foo = $bar/* || $bar = $foo/* ]]; then
    echo "Overlap"

Note that this won't work if one tree is sym-linked into the other.

| improve this answer | |
  • If I understand the original question correct, $foo and $bar should already be results from realpath, so you could use $foo and $bar directly instead of $rd1 and $rd2 – Bodo Jan 8 '19 at 10:05
  • @Bodo You are right, updated. – Ralf Jan 8 '19 at 10:14
  • Excellent! I didn't know that idiom. I think I need a / before the *, right? Also, man bash says there is no word splitting inside [[ ]], could I drop the double quotes there? – L. Levrel Jan 8 '19 at 16:35
  • Good catch! Yes, the / is needed. The quotes are not needed. I always follow: if in doubt: quote. I'll update. – Ralf Jan 8 '19 at 16:45
  • @Ralf thanks! I follow the same rule, but in an answer I think it's better to be as accurate as possible. I also did some tests about the quotes in foo="$(...)". The man is not very explicit about word splitting of the result of $(); I understand this result may be split according to the context, hence there is no word splitting here because variable assignments do not induce word splitting. Thanks again! – L. Levrel Jan 8 '19 at 19:22

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.