0

Complete Linux newbie and need help with command to find filenames, list their respective paths, and then further filter that result set by only the paths that contain a specific substring(s).

For example I have a filename identified as someFile.txt. This filename can exist in multiple directories:

E.g. /some/directory/path/good/someFile.txt and /some/directory/path/bad/someFile.txt

Using find I can return a list of all paths containing that file, but I'd like to return ones that only contain 'good' in the path name as well. Whitelisting in this example is preferable as there are many variable path names, but I know the ones containing the term 'good' are acceptable.

This is what I have that works:

$ find . -type f \( -name someFile1.txt -o -name someFile2.txt\)

I've also tried the following to no avail:

$ find . -type f \(-name someFile1.txt -o -name someFile2.txt\) -print0 | xargs -0 grep -rl 'good'
$ find . -type f \(-name someFile.txt .... | xargs -0 grep 'good'
$ find . -type f \(-name someFile.txt .... | xargs -0 egrep 'good|real_good'
1
  • No need for xargs - you just want to know if it's in the path, right? find ... | grep good
    – Panki
    Dec 16, 2020 at 18:52

1 Answer 1

2

Use the -path test with find:

find . -path '*/good/*' -type f \( -name someFile1.txt -o -name someFile2.txt \)

The -path test works like -name, but the pattern is tested against the complete pathname of whatever file find is currently considering.

The way I'm using the test above will ensure that only files with the names someFile1.txt or someFile1.txt that are located somewhere beneath a directory called good is returned by find.

If the files are supposed to reside in the good directory, and not in a subdirctory beneath it, then use

find . -type f \( -path '*/good/someFile1.txt' -o -path '*/good/someFile2.txt' \)

or something similar.

Obviously, if you are looking for actual files called someFile1.txt and someFile2.txt, you would be using the pattern someFile[12].txt rather than two separate tests.

From comments, it's clear that you may want to use

find . -type f \
    \( -ipath '*realgood*' -o -ipath '*real_good*' \) \
    \( -name someFile1.txt -o -name someFile2.txt  \)
5
  • I apologize that I wasn't entirely clear in my example as I tried to generalize it too much. Something closer to that I'm dealing with looks as follows: /somefilepath/moresubdirs_someDir_good_1_2/fileName1.txt or /somefilepath/moresubdirs_someDir_real_good_1_2/fileName1.txt. I appreciate your help though!
    – C_Squared
    Dec 16, 2020 at 19:00
  • @C_Squared So use *good* or *_good_* instead of */good/* with -path?
    – Kusalananda
    Dec 16, 2020 at 19:04
  • I also believe I found something that works through trial and error. $ find . -type f ( -name someFile.txt -o -name someOtherFile.txt) | egrep -i 'realgood|real_good'
    – C_Squared
    Dec 16, 2020 at 19:05
  • @C_Squared I wouldn't use grep on pathnames (as they can theoretically contain newlines). What you are showing there is the equivalent of \( -ipath '*realgood*' -o -ipath '*real_good*' \).
    – Kusalananda
    Dec 16, 2020 at 19:06
  • your ipath solution worked perfectly. Thanks!
    – C_Squared
    Dec 16, 2020 at 19:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .