0

How is it possible to make a Bash function handle properly filenames containing a whitespace when filenames are passed using wildcard?

$ touch a "a b" b
$ ls -1 *
a
a b
b

$ function foo { ls -1 $*; }
$ foo *
a
a
b
c

I'd like to define a function foo that returns the same results as ls -1 * does when executed as foo *. I tried $@ instead of $* but it didn't work either.

1

1 Answer 1

1

I'm not sure what your function is supposed to do, taking into consideration how it's called. But here's a possible solution.

foo () { ls -1 "$@"; }

This function is supposed to call ls -1 with the function's positional arguments passed to the command. How does it work?

$ touch a "a b" b
$ ls -1 .
a
a b
b
$ foo .
a
a b
b

And this one also works:

$ foo *
a
a b
b

But you need to know the difference between foo . and foo *. The former passes . as the argument to the function foo, and then it internally passes the same to ls -1. With foo * the situation is different as * is expanded to a list of arguments to the function foo, and then the arguments need to be handled internally. That's accomplished in my function with "$@", which expands the positional arguments taking care of whitespace. If you omit the quoting around $@, you end up with this:

$ goo () { ls -1 $@; }
$ goo .
a
a b
b
$ goo *
a
a
b
b

Finally, you can analyse the difference between "$*" and "$@".

$ hoo () { ls -1 "$*"; }
$ hoo .
a
a b
b
$ hoo *
ls: cannot access 'a a b b': No such file or directory

"$*" is not the right one here, definitely.

$ foo . .
.:
a
a b
b

.:
a
a b
b
$ hoo . .
ls: cannot access '. .': No such file or directory

Not the answer you're looking for? Browse other questions tagged .