Find file by matching on its path

I have a directory containing a number of subdirectories. Each of these subdirectories contains a subdirectory which all have the same name. I would like to produce a list of all these files on the command line. So, for example, if I have:

dir1/
    file1.txt
    subdir/
        relevant_file1.c
        relevant_file2.c
dir2/
    file2.txt
    subdir/
        relevant_file3.txt
        relevant_file4.java
dir3/
    subdir/
        relevant_file5.cpp
    irrelevant_subdir/
        unimportant_file.txt
dir4/
    subdir/

I would like to have the following output:

dir1/subdir/relevant_file1.c
dir1/subdir/relevant_file2.c
dir2/subdir/relevant_file3.txt
dir2/subdir/relevant_file4.java
dir3/subdir/relevant_file5.cpp

I presume this should not be too difficult using find, but I not quite been able to figure it out. It's difficult to search for this problem because it is so specific, and just searching for "find file by matching on its path" doesn't produce anything useful.


try this

find */subdir -type f

You don't actually need find for this. A simple ls will do:

$ ls -1 */subdir/*
dir1/subdir/relevant_file1.c
dir1/subdir/relevant_file2.c
dir2/subdir/relevant_file3.txt
dir2/subdir/relevant_file4.java
dir3/subdir/relevant_file5.cpp

Or, if you want to do something with those files and not just list them, use shell globs:

for file in */subdir/*; do command "$file"; done

Of course, that will list anything in any subdirectory called subdir. Including directories, symlinks, device files or anything else. If you want to limit it to normal files, use find "*/subdir" -type f as suggested by @Carl, or add a file test:

for file in */subdir/*; do [ -f "$file" ] && command "$file"; done

A better workaround with find is to use -path option.

find -path "*/subdir/*" -type f

It's more useful when we have a more complex structure. something like:

.
├── dir1
│   ├── gooddir
│   │   └── subdir
│   │       └── file.txt
│   ├── irrelevant_subdir
│   │   └── file.txt
│   └── subdir
│       └── file.txt
└── dir2
    ├── gooddir
    │   └── subdir
    │       └── file.txt
    ├── irrelevant_subdir
    │   └── file.txt
    └── subdir
        └── file.txt

In above example something like find */subdir -type f only finds files within a first subdir. However find -path "*/subdir/*" -type f will works fine.


Just use the appropriate tool:

locate "/subdir/"

You may want to (re-)run:

sudo updatedb

if you need to refresh locate's database (for exemple if you want to find recently added files), but it should be built via crontabs every day (if the pc is running at that time)

If you need the initial updatedb, it may seem slower than the specific find, but in the end it's way faster as all subsequent queries are done FAST.