In bash, I am trying to find directories containing a specific file; however, these directories are on different levels, eg, if I am looking for dir03/myfile.txt:
dir01/dir02/dir03/myfile.txt
dir01/dir03/ ##no target file in it
dir01/dir04/dir05/dir03/myfile.txt
dir01/dir04/dir05/dir06/myfile.txt ##I do not want this
I could do:
find ./dir01 -type -d -iname "dir03"
But then I would get all directories, even the ones without the target file
If I do this:
find ./dir01/*/dir03 -iname "myfile.txt"
I would not see "dir01/dir04/dir05/dir03/myfile.txt"
This does not work:
find ./dir01 -iname "dir03/myfile.txt"
##find: warning: Unix filenames usually don't contain slashes (though pathnames do).
That means that '-iname ‘dir03/myfile.txt’' will probably evaluate to false all the time on this system. You might find the '-wholename' test more useful, or perhaps '-samefile'. Alternatively, if you are using GNU grep, you could use 'find ... -print0 | grep -FzZ ‘dir03/myfile.txt’'
I can do this:
find ./dir01 -iname "myfile.txt" -print0 | grep -FzZ 'dir03' | sed "s/myfile\.txt/\n/g"
It finds all the matches where myfile.txt is, and gets only the ones contained by the target directory; after that, I split the results with a new line (the line above gives the results concatenated, eg ./dir01/dir02/dir03/myfile.txt./dir01/dir04/dir05/dir03/myfile.txt
But it might make the search more generic and longer in case I have a complex subdirectory structure. I was wondering if there was an easier solution to tell find to find "dir03/myfile.txt" at any level
Please note that the directory names are just for example sake, they do not share the same prefix.
Edit: I guess I could do
find ./dir01 -iname "myfile.txt" > myres0.txt
grep 'dir03' myres0.txt > myres1.txt
Considering that I am looking for multiple parental directories and not just dir03, it would do just one search, then I can use a txt file with my target directories and do:
grep -f mytargetDirs.txt myres0.txt > myres1.txt
Still wondering if there is a better way though.
Sounds like this is all you need:
find ./dir01 -type f -name 'myfile.txt' | grep '/dir03/[^/]*$'
Add NUL-termination options (-print0
and grep -Z
) to protect against newlines in directory/file names as you see fit.