find command behaviour when matching names without quotes

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?

1

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 
2

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' 
1
[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/ ./Downloads/ ./Downloads/ ./.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"

1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like