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
  • 280,126
  • 43
  • 390
  • 441
Niklas
  • 23,674
  • 33
  • 131
  • 170

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
  • 39,294
  • 7
  • 70
  • 76
  • 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
  • 280,126
  • 43
  • 390
  • 441