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.

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
add comment

3 Answers

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
add comment

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
add comment
[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
add comment

Your Answer

 
discard

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

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