Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

On Mac OS X or Linux, is there a simpler form of the command

find . -name "*substring_of_filename*"

which is to find all files having names containing substring_of_filename within the current directory (or some other given directory). Because it's a common thing to do, is there a way to make the command shorter and easier to type, possibly using an alias or function in Bash? Or is there some other easy-to-type command that can be used?

Such as:

findfile . substring_of_filename

(Note: The question as originally written used app_config as an example of substring_of_filename.)

share|improve this question

migrated from stackoverflow.com May 3 '11 at 9:09

This question came from our site for professional and enthusiast programmers.

2  
locate app_config –  knittl May 2 '11 at 15:00
1  
@knittl: But locate is not restricted to the current dir and it's subdirs. –  user unknown Nov 10 '12 at 5:25
add comment

10 Answers

The answer is "no". There is no shorthand for "find file by filename with substring in current directory or below" in GNU find. The aliases I use to work around this limitation are as follows (for zsh):

# find file in cwd by [S]ubstring, case [I]nsensitive, change to first sub[D]irectory
finds()   { find .  -name "*$**"; }
findsi()  { find . -iname "*$**"; }
findsid() { cd `find . -iname "*$**" | head -n1 | xargs dirname`; }

The last one is my favorite. These can be used as follows:

> ls -R
.:
file1  File2  HOLEFILE  test

./test:
hello

(that's the test directory)

> findsi file
./HOLEFILE
./File2
./file1

> finds file
./file1

> finds le
./File2
./file1

> findsid ell
> ls
hello
share|improve this answer
    
If anyone ports these to their shell of choice, feel free to edit this post and add your version. –  Alex Hirzel Apr 24 '13 at 9:42
add comment

If you use bash 4 (with shopt -s globstar) or zsh:

prinftf %s\\n **/*substring_of_filename*
share|improve this answer
add comment

Here's your bash function, put it in .bashrc:

function findfiles { find "$1" -iname "*$2*"; }

(Note that -iname makes the search case-insensitive. If you don't want that, use -name instead.)

share|improve this answer
    
You can also run this in a bash session if you want to use it just for the current session. –  Wuffers May 7 '11 at 1:19
    
iname is not equivalent, name is. It might be your favorite usage, but was not the question. –  user unknown Nov 10 '12 at 5:27
add comment

I think just grep can do it fine, no need for find. Relevant options from the manpage:

 -l, --files-with-matches
          Suppress  normal  output;  instead  print the name of each input
          file from which output would normally have  been  printed.   The
          scanning  will  stop  on  the  first match.  (-l is specified by
          POSIX.)

 -H, --with-filename
          Print  the  file  name for each match.  This is the default when
          there is more than one file to search.

 -R, -r, --recursive
          Read all  files  under  each  directory,  recursively;  this  is
          equivalent to the -d recurse option.

Note that even if -H is the default when there's more than one file to search, I still suggest you to use it explicitly. This switch solves a particular problem of yours, it's better to remember this bit of directly related knowledge than the edge case (searching multiple files) when this option is the default.

So the grep version of your original find command will look like this:

grep -lHR app_config .
share|improve this answer
1  
I suspect "all files having the app_config in it" really meant "all files having app_config in their names". –  Eroen Mar 5 '12 at 1:56
add comment

On Mac OS X you may also put an alias using mdfind into .bashrc:

# mdfind uses Spotlight 
alias findf='mdfind -onlyin . -name'

findf app_config
share|improve this answer
add comment

On most Linux distributions, you can use locate. For example:

$ locate find | grep bin
/sbin/findfs
/usr/bin/find
/usr/bin/find2perl
/usr/bin/findsmb
/usr/bin/gst-typefind-0.10
/usr/bin/memdiskfind
/usr/bin/oldfind
/usr/bin/sane-find-scanner
/usr/include/c++/4.5/ext/pb_ds/detail/bin_search_tree_/find_fn_imps.hpp
/usr/include/c++/4.5/ext/pb_ds/detail/binary_heap_/find_fn_imps.hpp
/usr/include/c++/4.5/ext/pb_ds/detail/binomial_heap_base_/find_fn_imps.hpp
share|improve this answer
add comment

On OS X, Why not just use locate? Granted the locatedb isn't updated very often by default, but you can change that easily (change the periodic job scheduling on OS X). locate is a BSDism, don't know if it's on Linux or not.

share|improve this answer
    
In some scenarios locatedb is a security risk. LUKS-encrypted home directory + not encrypted root + updatedb indexing /home and storing its cache somewhere in /var (which is not encrypted) leaks filenames from /home. –  vtest May 7 '11 at 22:53
add comment

Instead of doing this in a bash, zsh, tcsh, sh, etc... script I made a TextExpander shortcut. I type sh≤Space≥ and TE types

find . -iname "**"

and puts the cursor between the asterisks.

share|improve this answer
add comment

Put this either in your ~/.profile or ~/.bashrc, not sure which one Mac uses:

findname () 
{ 
    find . -name "*$1*"
}

then call the function by findname name_of_file

if you wanted to use multiple words, you'd have to get more complicated..the easiest way I can think of offhand is this:

findname() 
{ 
    find .|grep $1|grep $2|grep $3|grep $4 
}

That will find every file in your current dir, search for string 1, then search that result for string 2, and etc, till it gets to 4.

share|improve this answer
    
The second function doesn't work unless the variables are quoted like find . |grep "$1" |grep "$2" |grep "$3" |grep "$4". Also, it searches for parts of the path rather than parts of filenames. –  Arne Stenström Mar 28 '13 at 13:12
add comment

Au contraire! There is an even more complicated one, but one, which works:

find . -name "*app_config*"

The dot isn't neccessary for gnu-find:

find -name "*app_config*"

But you have to mask the asterixs, else they will be interpreted by the shell, and you will only find filenames which match the ones in the current directory, which match "*app_config*".

share|improve this answer
    
seems not true at least on Mac OS X –  Ruler Theodore May 2 '11 at 15:23
    
What seems not true? That you can omit the dot? Or that a file which contains 'app_config' in its name and which is in the current directory, will restrict the search to his name. –  user unknown May 2 '11 at 15:51
    
I mean on Mac OS X, you can use find . -name *app_config* without the quotes –  Ruler Theodore May 2 '11 at 15:57
1  
@BenU: I don't have a System with Mac OS X, but on Linux, the need for quotes arises from the shell. If I don't quote the "*", the shell tries to expand it. It is not needed needed for find, and not, if the * doesn't match something in the current dir - then it is passed unchanged to find. You may try single quotes, which are allowed too in bash, but would prevent variable expansion (which isn't the case, here, but sometimes else) -name "*.pdf.$id" for example. –  user unknown Nov 10 '12 at 5:13
1  
For the record, quotes should be used in OS X just the same way as in Linux, since OS X has the same Bash shell as Linux. –  Arne Stenström Mar 28 '13 at 11:56
show 2 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.