I was doing a

find . -iname '*sitesearch*' | grep demo

because I know the file should be some/path/SiteSearch/demo/SiteSearch.html, but it turned out a person put the file in as some/path/SiteSearch/demo/index.html, so the file cannot be found.

Is there a better way to do the search?

Such as for this case, if I do

find . -iname '*demo*' | grep -i sitesearch

it would have found it. But I don't want to always THINK what possibility it is and figure out what pattern to use. I just want a way that whenever the file and path have both of these 2 keywords, then print it out. For example, if there is a way to ls all files will the full path on each line, then we can do

ls --some-flags | grep -i demo | grep -i sitesearch

or maybe another way / better way.


You can combine two patterns (or more generally multiple criteria) in find.

find . -ipath '*sitesearch*' -ipath '*demo*'

or if you prefer regex syntax

find . -iregex '.*sitesearch.*' -iregex '.*demo.*'

ls with the full path on each line” (plus traversing directories recursively, which is evidently needed here) would be find. While you can run find | grep -i demo | grep -i sitesearch, doing it all with find is likely to be visibly faster.

If you do this a lot, you can make it a function (put it in your ~/.kshrc or ~/.bashrc or ~/.zshrc):

findallof () {
  typeset -a pred
  typeset x
  for x do
    pred=("${pred[@]}" -ipath "*$x*")
  find "${pred[@]}"

Note also that you can search for files by name with locate (check the man page on your system as there are several implementations even on Linux).

locate -i sitesearch | grep -i demo

This can be faster than looking through a large directory tree, because locate queries an index (though case-insensitive searches tend not to be that fast). However, the index is typically rebuilt only every night, so it won't show files created today. Files that are not in a publicly readable directory may or may not be indexed depending on the implementation (check if /usr/bin/locate is a setuid root binary: if it is, private files are indexed and the locate command shows you only the files you can access).

  • Needs -ipath instead of -iname or it won't find some/path/SiteSearch/demo/index.html like grep would. Also a missing * after demo. – frostschutz Apr 6 '13 at 0:33
  • later on, I found that find . | grep -i demo | grep -i sitesearch should do the job too. But your solution is just one command so it should be nicer. Do you know how to make it into functions so that we can just say find1 sitesearch or find2 demo sitesearch or if better we don't need to say find1 or find2 but just findallof – nonopolarity Apr 6 '13 at 2:10
  • @動靜能量 You can make it a function (see my edit). – Gilles 'SO- stop being evil' Apr 6 '13 at 12:01
  • this function doesn't work on a Mac... do you have a version that might work on both the Mac and Linux? – nonopolarity Apr 7 '13 at 7:01
  • @動靜能量 With . after find? GNU find doesn't need it, but I think BSD find does. – Gilles 'SO- stop being evil' Apr 7 '13 at 13:51

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.