5

This question already has an answer here:

I'm trying to find all the javascript files in subdirectories of my project.

The working tree is as follows:

.
├── app
├── assets
├── components
├── email.txt
├── gulpfile.js
├── node_modules
└── package.json

For that end I say:

find . -name *.js

or

find . -path *.js

Strangely, first command reports only gulpfile.js, while the second one reports nothing. But I have .js files in app, components and node_modules! Why wouldn't they show up?

marked as duplicate by Kusalananda, countermode, Michael Homer, Jeff Schaller, Mongrel Feb 6 '17 at 10:50

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 1
    Use single quotes on the file name, as find . -name '*.js' – LouisB Feb 6 '17 at 1:06
8

Put single quotes around *.js. Without quotes, the shell is expanding the wildcard to filenames that match in the current directory, so find only gets those filenames, either in the current directory or sub-directories in the find spec (but never sees the wildcard). To specify it as a pattern for find to use, you need to prevent the shell expansion. '*.js' does that.

2

It's easy to forget that shell globbing still plays a role in the process. Thus you need a way to tell shell to avoid expanding * to a list of files. One way is via what Chris Johnson mentioned - quoting.

Another is via escaping the * character, as in

find . -iname \*.js

Compare:

$ strace -e trace=execve find -maxdept 1 -iname *.js > /dev/null                                      
execve("/usr/bin/find", ["find", "-maxdept", "1", "-iname", "file1.js", "file2.js"], [/* 75 vars */]) = 0
find: unknown predicate `-maxdept'
+++ exited with 1 +++

$ strace -e trace=execve find -maxdept 1 -iname \*.js > /dev/null                                     
execve("/usr/bin/find", ["find", "-maxdept", "1", "-iname", "*.js"], [/* 75 vars */]) = 0
find: unknown predicate `-maxdept'
+++ exited with 1 +++

In first case we see that * was expanded to list of files file1.js and file2.js that are present in the current working directory. In second example - the * is treated as literal argument to find. In fact, this is the same result produced by quoting the argument:

$ strace -e trace=execve find -maxdept 1 -iname '*.js' > /dev/null                                    
execve("/usr/bin/find", ["find", "-maxdept", "1", "-iname", "*.js"], [/* 75 vars */]) = 0
find: unknown predicate `-maxdept'
+++ exited with 1 +++

Alternatively , you could use the octal value of * instead.

$ strace -e trace=execve find -maxdept 1 -iname $'\52'.js > /dev/null                                 
execve("/usr/bin/find", ["find", "-maxdept", "1", "-iname", "*.js"], [/* 75 vars */]) = 0
find: unknown predicate `-maxdept'
+++ exited with 1 +++

Not the answer you're looking for? Browse other questions tagged or ask your own question.