How to find directory in directory?

How can I find a directory with a certain name but only if it is in another directory with a certain name? For example when I have the following directory structure

a
├── b
│   └── e
├── c
│   └── e
└── d

I’d like to find the directory ‘e’, but only when it is located in a directory called ‘c’. If possible with the find command alone without using grep.

Asked By: simon

||

Use GNU find with -path that searches the entire path for a match:

$ find . -path '*/c/e'
./a/c/e

That will match any file or directory called e which is in a directory called c.

Alternatively, if you don’t have GNU find or any other that supports -path, you can do:

$ find . -type d -name c -exec find {} -name e ;
./a/c/e

The trick here is to first find all c/ directories and then search only in them for things called e.

Answered By: terdon

Since you have tagged Bash, an alternative is to use globstar:

shopt -s globstar # Sets globstar if not already set
# Print the matching directories
echo **/c/e/
# Or put all matching directories in an array
dirs=(**/c/e/)
Answered By: Quasímodo

Using the Fd tool:

fd -t d --full-path /c/e$

https://github.com/sharkdp/fd

Answered By: Zombo

In addition to @terdon ‘s solution, I provide here an alternative version for those without GNU find (that I only could find by following his idea!):

find . -type d -name 'c' -exec find '{}/e' -type d ( -name 'e' -ls -o -prune ) ; 2>/dev/null 

This seems to work on my machine

To test:

# add files under each directories as otherwise some solutions would 
# list also files under any "c/e" subdirs ... 
# in a subdir : do  : 
mkdir -p a b c a/b a/c a/c/e a/c/d/e a/c/d/e/c/e/f/g
for i in $(find */ -type d -ls); do ( cd "$i" && touch a b c d e ) ; done 
# this will creates several files under each subdirs, wherever it can (ie, when they don't match a subdir's name).
# then test:
find . -type d -name 'c' -exec find '{}/e' -type d ( -name 'e' -ls -o -prune ) ; 2>/dev/null 
# and it answers only the 2 matching subdirs that match name "c/e":
inode1 0 drwxr-xr-x   1 uid  gid   0 nov.  2 17:57 ./a/c/e
inode2 0 drwxr-xr-x   1 uid  gid   0 nov.  2 18:02 ./a/c/d/e/c/e
Answered By: Olivier Dulac
Categories: Answers Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.