Is there a simpler form of find . -name "*substring_of_filename*" on Mac OS X and Linux?

4

3

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.)

Ruler Theodore

Posted 2011-05-02T14:46:41.870

Reputation:

2locate app_config – knittl – 2011-05-02T15:00:05.057

1@knittl: But locate is not restricted to the current dir and it's subdirs. – user unknown – 2012-11-10T05:25:40.033

Answers

5

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

chad

Posted 2011-05-02T14:46:41.870

Reputation: 51

3

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.)

Janus Troelsen

Posted 2011-05-02T14:46:41.870

Reputation: 1 958

You can also run this in a bash session if you want to use it just for the current session. – Wuffers – 2011-05-07T01:19:31.940

iname is not equivalent, name is. It might be your favorite usage, but was not the question. – user unknown – 2012-11-10T05:27:40.593

2

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".

user unknown

Posted 2011-05-02T14:46:41.870

Reputation: 1 623

seems not true at least on Mac OS X – None – 2011-05-02T15:23:24.380

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 – 2011-05-02T15:51:25.457

I mean on Mac OS X, you can use find . -name *app_config* without the quotes – None – 2011-05-02T15:57:19.277

But do you have a file called fooapp_configbar in the starting directory? You can use the command without quotes on Linux, for example, too, and it will leave the asterix untouched, if there is no matching file in the current directory at the very first level. – user unknown – 2011-05-02T16:55:46.630

Thanks, @user_unknown. I couldn't figure out why I wasn't getting find ~ -name "*.pdf" to work on my mac os x until I tried leaving out the quotes. In Mac OS X, it seems that one must leave out the quotes. – BenU – 2012-11-10T00:22:04.360

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 – 2012-11-10T05:13:41.717

1For 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 – 2013-03-28T11:56:29.227

1

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.

Matt

Posted 2011-05-02T14:46:41.870

Reputation: 627

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 – 2013-03-28T13:12:19.200

0

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.

Mark Thalman

Posted 2011-05-02T14:46:41.870

Reputation: 990

0

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.

tamouse

Posted 2011-05-02T14:46:41.870

Reputation: 101

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 – 2011-05-07T22:53:31.290

0

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

Xenoactive

Posted 2011-05-02T14:46:41.870

Reputation: 992

0

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

prinftf %s\\n **/*substring_of_filename*

Lri

Posted 2011-05-02T14:46:41.870

Reputation: 34 501

0

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

Alex Hirzel

Posted 2011-05-02T14:46:41.870

Reputation: 996

If anyone ports these to their shell of choice, feel free to edit this post and add your version. – Alex Hirzel – 2013-04-24T09:42:32.800

-1

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 .

vtest

Posted 2011-05-02T14:46:41.870

Reputation: 4 424

2I suspect "all files having the app_config in it" really meant "all files having app_config in their names". – Eroen – 2012-03-05T01:56:37.860