Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

What effect does "shopt -s extglob" has on "find" command in bash ?

152 views
Skip to first unread message

Eric

unread,
Feb 1, 2008, 3:16:25 AM2/1/08
to
I have turned on extglob in bash, but it behaves very strange when I
use find command. Please see:

shsvr:/home/tom/tmp/test1$ echo $SHELL
/bin/bash
shsvr:/home/tom/tmp/test1$ shopt -s extglob
shsvr:/home/tom/tmp/test1$ ls *
-rw-r--r-- 1 tom msc 0 Feb 1 15:47 File1.java
-rw-r--r-- 1 tom msc 0 Feb 1 15:47 File2.java
-rw-r--r-- 1 tom msc 0 Feb 1 15:47 Makefile

SCCS:
total 0
-rw-r--r-- 1 tom msc 0 Feb 1 15:47 s.File1.java
-rw-r--r-- 1 tom msc 0 Feb 1 15:47 s.Makefile
-rw-r--r-- 1 tom msc 0 Feb 1 15:47 s.File2.java

shsvr:/home/tom/tmp/test1$ find . -name !(s.*.java)
find: paths must precede expression
Usage: find [path...] [expression]

shsvr:/home/tom/tmp/test1$ find SCCS -name !(s.*.java)
find: paths must precede expression
Usage: find [path...] [expression]

shsvr:/home/tom/tmp/test1$ cd SCCS
shsvr:/home/tom/tmp/test1/SCCS$ find . -name !(s.*.java)
./s.Makefile

What should I do to make find works properly ?

Thanks in advance.

Bill Marcum

unread,
Feb 1, 2008, 6:14:24 AM2/1/08
to
On 2008-02-01, Eric <rc.c...@gmail.com> wrote:
>
>
> I have turned on extglob in bash, but it behaves very strange when I
> use find command. Please see:
>

>


> shsvr:/home/tom/tmp/test1$ find . -name !(s.*.java)
> find: paths must precede expression
> Usage: find [path...] [expression]
>

The argument following -name is usually quoted so the shell won't expand
it. Find is an external command, so its globbing isn't affected by bash
shopt options, but you can use:

find . ! -name 's.*.java'

Stephane Chazelas

unread,
Feb 1, 2008, 6:41:54 AM2/1/08
to

Note that strictly speaking, find is not doing globbing, that is
it doesn't expand the wildcard pattern into a list of files as
the shell does. Instead it uses the pattern on the basename of
every file it is walking through to decide whether it matches or
not (and going on or not with the other predicates). So it is
doing "matching" only.

In shells, wildcard patterns can be used both for globbing
(filename generation) as in

echo *.txt
which it expands into echo x.txt y.txt...
or for matching as in

case $text in
($pattern) ...
esac

or ${var#$pattern}...

--
Stephane

Eric

unread,
Feb 1, 2008, 6:54:47 AM2/1/08
to
On Feb 1, 7:41 pm, Stephane Chazelas <stephane_chaze...@yahoo.fr>
wrote:

> On Fri, 1 Feb 2008 06:14:24 -0500, Bill Marcum wrote:
> Stephane- Hide quoted text -
>
> - Show quoted text -


Thanks. I know now. I just want a more powerful find utility so that I
can find files using very complicated criteria(regular expressions).
Are there any kinds of tool available ? I am puzzled that why there
is no an enhanced find utility. Its filename matching is too weak.

Stephane Chazelas

unread,
Feb 1, 2008, 6:59:03 AM2/1/08
to
On Fri, 1 Feb 2008 03:54:47 -0800 (PST), Eric wrote:
[...]

> Thanks. I know now. I just want a more powerful find utility so that I
> can find files using very complicated criteria(regular expressions).
> Are there any kinds of tool available ? I am puzzled that why there
> is no an enhanced find utility. Its filename matching is too weak.

GNU and FreeBSD find have the -iregex and -regex predicate which
should be enough for any need.

But in any case, you can run any utility to do the matching with
the -exec predicate.

find . -exec awk 'BEGIN{exit(!(ARGV[1] ~ /pattern/))}' {} \; -print

for instance.

--
Stephane

Stephane Chazelas

unread,
Feb 1, 2008, 7:03:05 AM2/1/08
to
[...]

or of course:

find . -exec bash -c '
shopt -s extglob
case $1 in
(pattern) exit 0;;
(*) exit 1;;
esac' inline {} \; -print

(of course that won't be as fast as using find's own matching
operators)

Note that the zsh shell has the ability to replace find with its
recursive globbing:

print -rl -- **/complex-pattern

for instance.

--
Stephane

Eric

unread,
Feb 1, 2008, 7:32:57 AM2/1/08
to
On Feb 1, 8:03 pm, Stephane Chazelas <stephane_chaze...@yahoo.fr>
wrote:

Great! Thank you very much.

Dan Mercer

unread,
Feb 1, 2008, 4:57:00 PM2/1/08
to

"Eric" <rc.c...@gmail.com> wrote in message news:47e375f8-8f5f-4003...@s37g2000prg.googlegroups.com...
: I have turned on extglob in bash, but it behaves very strange when I

: use find command. Please see:
:
: shsvr:/home/tom/tmp/test1$ echo $SHELL
: /bin/bash
: shsvr:/home/tom/tmp/test1$ shopt -s extglob
: shsvr:/home/tom/tmp/test1$ ls *
: -rw-r--r-- 1 tom msc 0 Feb 1 15:47 File1.java
: -rw-r--r-- 1 tom msc 0 Feb 1 15:47 File2.java
: -rw-r--r-- 1 tom msc 0 Feb 1 15:47 Makefile
:
: SCCS:
: total 0
: -rw-r--r-- 1 tom msc 0 Feb 1 15:47 s.File1.java
: -rw-r--r-- 1 tom msc 0 Feb 1 15:47 s.Makefile
: -rw-r--r-- 1 tom msc 0 Feb 1 15:47 s.File2.java
:
: shsvr:/home/tom/tmp/test1$ find . -name !(s.*.java)

This expanded to find . -name File1.java File2.java Makefile SCCS

-name doesn't support extended globbing and the patterns should be quoted
to avoid unintended expansion by the shell. What you really want is:

find . ! -name 's.*.java'

Dan Mercer

: find: paths must precede expression

Eric

unread,
Feb 1, 2008, 8:22:38 PM2/1/08
to
One more question related to find utility in UNIX: How do we can
specify a more complicated path criteria ? Can we use the "shopt -s
extglob" ?
Please see the following examples where some succeed while others
fail:
shsvr:/home/tom/tmp$ ls
total 20
-rwsrwxrwx 1 tom msc 9 Jan 19 18:08 file1*
-rwxrwxrwx 1 tom msc 66 Jan 23 19:59 t*
drwxr-xr-x 3 tom msc 4096 Feb 1 15:47 test1/
drwxr-xr-x 3 tom msc 4096 Feb 1 20:16 test2/
drwxr-xr-x 2 tom msc 4096 Feb 2 08:56 test3/
shsvr:/home/tom/tmp$ ls test3/
total 0
-rw-r--r-- 1 tom msc 0 Feb 2 08:56 A.java

shsvr:/home/tom/tmp$ find '!(test1|test2)' -type f
find: invalid predicate `!(test1|test2)'

shsvr:/home/tom/tmp$ find !(test1|test2) -type f
file1
t
test3/A.java

shsvr:/home/tom/tmp$ find (test1|test2) -type f
bash: syntax error near unexpected token `|'

shsvr:/home/tom/tmp$ find '(test1|test2)' -type f
find: invalid predicate `(test1|test2)'

shsvr:/home/tom/tmp$ find test1|test2 -type f
bash: test2: command not found

shsvr:/home/tom/tmp$ find 'test1|test2' -type f
find: test1|test2: No such file or directory

shsvr:/home/tom/tmp$ find test[1-3] -type f
test1/SCCS/s.File1.java
test1/SCCS/s.Makefile
test1/SCCS/s.File2.java
test1/File1.java
test1/File2.java
test1/Makefile
test2/SCCS/s.File1.java
test2/SCCS/s.Makefile
test2/SCCS/s.File2.java
test2/File1.java
test2/File2.java
test2/Makefile
test3/A.java

Bill Marcum

unread,
Feb 2, 2008, 12:56:46 AM2/2/08
to
On 2008-02-02, Eric <rc.c...@gmail.com> wrote:
>
>
> One more question related to find utility in UNIX: How do we can
> specify a more complicated path criteria ? Can we use the "shopt -s
> extglob" ?

shopt only affects the shell. As someone else replied earlier, with GNU
or BSD find you can use -regex instead of -name. Otherwise you can pipe
the output of find to grep or other programs.


> Please see the following examples where some succeed while others
> fail:
> shsvr:/home/tom/tmp$ ls
> total 20
> -rwsrwxrwx 1 tom msc 9 Jan 19 18:08 file1*
> -rwxrwxrwx 1 tom msc 66 Jan 23 19:59 t*
> drwxr-xr-x 3 tom msc 4096 Feb 1 15:47 test1/
> drwxr-xr-x 3 tom msc 4096 Feb 1 20:16 test2/
> drwxr-xr-x 2 tom msc 4096 Feb 2 08:56 test3/
> shsvr:/home/tom/tmp$ ls test3/
> total 0
> -rw-r--r-- 1 tom msc 0 Feb 2 08:56 A.java
>
> shsvr:/home/tom/tmp$ find '!(test1|test2)' -type f
> find: invalid predicate `!(test1|test2)'
>

You can exclude directories with -prune.
find . -name 'test[12]' -prune -o -type f

0 new messages