Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I was looking for differences in the find command with double quotes and without quotes.

I found something odd. I have two files:

  • xWrapper.java
  • YWrapper.java

and some in the pattern *Wrapper.java.

I ran

find . -name *Wrapper.java

which should return the first file that matches the pattern, because the command expands as

find . -name xWrapper.java yWrapper.java ..

But as a result, I got the all the files of that form. Why did it return all the files matching that pattern?

share|improve this question
1  
You should have actually gotten an error about "paths must precede expression" or "unknown primary or operator" depending on the version of find you use (GNU vs BSD). – slhck Jul 31 '12 at 7:19

If anything you should get an error message if you are in the same catalog:

~$ mkdir test
~$ cd test
~/test$ touch {X,Y}Wrapper.java
~/test$ find . -name *Wrapper.java
find: paths must precede expression: YWrapper.java
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]

since the asterisk will be expanded, and -name only takes a single argument.

If you come from a location where the asterisk is not expanded:

~/test$ cd ..
~$ find test -name *Wrapper.java
test/XWrapper.java
test/YWrapper.java

Since the asterisk is now not expanded (as long as it does not match anything in the current directory), find sees it "as is", and uses it as a wildcard.

You should wrap the -name argument in single quotes to avoid such context dependent behavior:

~/test$ find . -name '*Wrapper.java'
./XWrapper.java
./YWrapper.java
share|improve this answer
    
Double quotes would work here as well. – chepner Jul 31 '12 at 12:00
1  
@chepner: Yes, correct. One can also escape the asterisk with backslash for the same effect. I thought of my formulation after I posted, and since single quotes can help against other possible string issues (escape characters specific to the shell), I let it stand as recommended practice, since it in this case concerns a string that most definitely is meant to be taken literally. – Daniel Andersson Jul 31 '12 at 12:39

You can use the or function because -name is a single string argument.

find . \( -name "xWrapper.java" -o -name "yWrapper.java" \)

Or you can use regex to find the file with

find . -regex '.*\(x\|y\)Wrapper.java'
share|improve this answer
2  
This was not really the question. It was about why find behaved as it did with unquoted asterisks. – Daniel Andersson Jul 31 '12 at 7:35
[max@localhost ~]$ touch 1file
[max@localhost ~]$ touch 2file
[max@localhost ~]$ touch 3file
[max@localhost ~]$ touch 4file
[max@localhost ~]$ touch 5file
[max@localhost ~]$ find -name "*file"
./4file
./2file
./Desktop/new file
./Desktop/DESKTOP/new file
./.bash_profile
./#file
./3file
./1file
./5file
./file
./file/file

This will match all the filename ending with file

[max@localhost ~]$ find . -name 'file*'
./file1
./.gconf/apps/file-roller
./Downloads/opera-10.60-6386.i386.linux/share/opera/unite/fileSharing.ua
./Downloads/opera-10.60-6386.i386.linux/share/opera/defaults/filehandler.ini
./Downloads/opera-10.60-6386.i386.linux/share/opera/styles/images/file.png
./.gnome2/file-roller
./.local/share/Trash/files
./file
./file/file2
./file/file

This will match all the filename staring with file

[max@localhost ~]$ find -name "1file"
./1file

This will match only filename 1file

[max@localhost ~/avi]$ touch a
[max@localhost ~/avi]$ touch b
[max@localhost ~/avi]$ touch "a b"
[max@localhost ~/avi]$ ll
total 0
-rw-rw-r-- 1 max max 0 Jul 31 13:49 a
-rw-rw-r-- 1 max max 0 Jul 31 13:49 a b
-rw-rw-r-- 1 max max 0 Jul 31 13:49 b
[max@localhost ~/avi]$ find . -name a
./a
[max@localhost ~/avi]$ find . -name b
./b
[max@localhost ~/avi]$ find . -name a b
find: paths must precede expression: b
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] 
[expression]
[max@localhost ~/avi]$ find . -name "a b"
./a b

(" or ') symbol will useful when there is a space in between filename like "a b"

share|improve this answer
    
This was not really the question. He wonders why his specific example behaved as it did in the interplay of find and Bash. – Daniel Andersson Jul 31 '12 at 11:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .