Within a set of directories, how do I find a file whose name includes a given string, such as "abcde"?


find will look through a directory structure and return results based on a glob:

find /your/dir -name "*abcde*"

Adding the -type f switch will refine your search criteria to only return files.

find /your/dir -type f -name "*abcde*"

You could also include other switches like -maxdepth 2 to restrict the search to 2 levels of directories bellow the specified one.

In this way you can build up a rich, highly targetted search command that will quickly return exactly what you need.

man find has a wealth of detail, including actions like -exec to run a command on the files returned by find and options to use regular expressions.

  • 3
    You might also want to add -type f to the find so that you only get results that are files. find /your/dir -type f -name "*abcde*" – Steven Pritchard Aug 1 '11 at 12:46
  • Good point Steven: I'll update my answer. Thank you. – jasonwryan Aug 1 '11 at 18:30

Use find:

find path-to-search -name '*abcde*'

If locate suits you (it is fast, but only as good as the most recent run of sudo updatedb). You can run locate using its own built-in regex facility...

Here is a parameter driven script to do what you want. Call it with $1 as the "abcde" you are looking for and with subsequent parameters as the directories:

a=("$@"); r=''
for ((i=1;i<${#a[@]};i++)); do r="$r|${a[i]}"; done
locate --regex  "(${r:1}).*/[^/]*${a[0]}[^/]*$"

An example call looks like this:

$ ./script_name 'z' "$HOME/bin/perl" "$HOME/type/stuff"

As suggested by jasonwryan, here is a commented version of the script.
Bear in mind that locate always outputs fully-qualified paths.


# Note: Do not use a trailing / for directory names
# Any of the args can be an extended regex pattern. 
# Create an array `a` which contains "$1", "$2", "$3", etc... (ie. "$@")
# writing the $-args to an array like this (using quotes) solves 
#   any possible problem with embedded whitespace 
# Set up an empty string which is to be built into a regex pattern 
#   of all directroy names (or an appropriate regex pattern)
# Each regex pattern is to be an extended regex    
# Each regex pattern is concatenated to the preceding one 
#   with the  extended-regex 'or' operator |
# Step through the array, starting at index 1 (ie, $2),
#   and build the 'regex-pattern' for the directories 
for ((i=1;i<${#a[@]};i++)); do r="$r|${a[i]}"; done
# Run 'locate' with
#                           |the target file pattern $1  | 
#                |zero-to-| |preceded and followed by    |
#                |-many   | |zero-to-many non-slash chars|
#                |anything| |               |‾‾‾‾‾‾‾‾‾‾‾‾
#                 ‾‾‾‾‾‾‾|| |               |   
locate --regex  "(${r:1}).*/[^/]*${a[0]}[^/]*$"
#        ________|      |  | 
#       |directory-regex| last
#       | in brackets ()| slash      
#       |stripped of its|
#       |leading "|"    |
  • Upvoted for the script: but it would be helpful to (extensively) comment it so it is clear as to what is actually going on in there... – jasonwryan Aug 1 '11 at 4:34
  • Nice job, fred! I'd upvote again if I could. Thank you. – jasonwryan Aug 1 '11 at 8:37
locate abcde | egrep "(dirA|dirB|dirC)" 

for the set of directories dirA, dirB, dirC.

Or 3 find-commands.

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.