candied_orange
candied_orange

Reputation: 7354

Using find with regex, exec, a glob, and a little concatenation

If I type

find . -type d -regex ".*src/main/groovy/.*" -exec echo groovyc -d classes {}/* \;

            This finds matching paths below cwd and passes each to echo with {}
I get

groovyc -d classes ./mine/app/src/main/groovy/mine/*

            This compiles groovy source files found in glob

which, if I copy and paste, runs flawlessly.

But if I take the echo out of that first line like this

find . -type d -regex ".*src/main/groovy/.*" -exec groovyc -d classes {}/* \;

I get

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed: 
./mine/app/src/main/groovy/mine/*: ./mine/app/src/main/groovy/mine/* (No such file or directory)

What foul magic is this? Why does concatenating {} with /* only work when echo is involved? How to fix this?

Upvotes: 0

Views: 302

Answers (1)

tjm3772
tjm3772

Reputation: 3219

As noted, Filename Expansion is something that a shell does for you. Programs don't automatically recognize * as a wildcard to match all files in a directory. If you want Filename Expansion to occur then you need to run your command in a shell.

Two examples:

# launch a shell for each directory found
find . -type d -regex ".*src/main/groovy/.*" \
-exec /bin/bash -c 'groovyc -d classes "$1"/*' _ {} \;

# launch one shell to handle all directories
find . -type d -regex ".*src/main/groovy/.*" \
-exec /bin/bash -c 'for dir ; do groovyc -d classes "$dir"/* ; done' _ {} +

Upvotes: 1

Related Questions