2

I have the following function f() { find . -name "$1"} which is just a handy shortcut for finding the file with a name. If I execute find . -name "*.gradle" in the terminal I get:

./.gradle
./app/build.gradle
./build.gradle
./dependencies.gradle
./settings.gradle
./wearable/build.gradle

If I execute f *.gradle in the terminal I get:

./app/build.gradle
./build.gradle
./wearable/build.gradle

The first result is the correct one and also the wanted one. Why am I getting though this 'wrong' result when using my function even though the content is the same? Did I inject the $1 parameter wrongly?

Charles Duffy
  • 257,635
  • 38
  • 339
  • 400
Niklas
  • 20,301
  • 31
  • 118
  • 158

2 Answers2

4

You need to use quotes to prevent the expansion beforehand in the current shell and let the expansion take place within the function:

f '*.gradle'
heemayl
  • 35,775
  • 6
  • 62
  • 69
  • Is it possible to make `f *.gradle` work without using the `'`? – Niklas Apr 21 '16 at 21:03
  • @Niklas Then you need to use `$@` to indicate all positional parameters inside `f` (not just the first one): `f () { find . -name "$@" ;}` – heemayl Apr 21 '16 at 21:05
  • @heemayl, that wouldn't actually work here -- you'd need to construct `-name "$1" -o -name "$2"`, etc., and even then, it would only include files whose names matched glob targets in the current directory, not in children. – Charles Duffy Apr 21 '16 at 21:17
2
f *.gradle

expands the glob, replacing *.gradle with a list of files in the current directory, which then may run something like the following:

$ f one.gradle two.gradle
#   $1         $2

which then runs:

find . -name one.gradle

...passing only the first file ($1), and ignoring all others.


If you want to pass the glob through to find:

f '*.gradle'
Charles Duffy
  • 257,635
  • 38
  • 339
  • 400