1
$ ls -l
total 0
-rw-rw-r-- 1 t t 0 Jun  8 16:37 'file; echo hello'
$ find . -exec echo {} \;
.
./file; echo hello

I was wondering why the following command doesn't ls -l each file in the current directory? Why does it report some file named 1? Thanks.

$ find . -exec sh -c "ls -l $@" sh {} \;
ls: cannot access '1': No such file or directory
ls: cannot access '1': No such file or directory

$ find . -exec sh -c "echo ls -l $@" sh {} \;
ls -l 1
ls -l 1
Tim
  • 98,580
  • 191
  • 570
  • 977

1 Answers1

2

In both cases, $@ is expanded by your current shell, before it runs find, because it’s in a double-quoted string. I’m guessing you have $1 set to 1 (run printf "%s\n" "$@" to see the current values of the positional parameters).

To run your experiments as I think you intend, you should use single quotes around the command and double quotes around $@ (to avoid extra splitting); for example:

find . -exec sh -c 'ls -l "$@"' sh {} \;
Stephen Kitt
  • 411,918
  • 54
  • 1,065
  • 1,164
  • Thanks. `find . -exec sh -c 'ls -l "$@"' sh {} \;` seems better, in that it can prevent word splitting which `find . -exec sh -c "ls -l \$@" sh {} \;` and `find . -exec sh -c "ls -l '$@'" sh {} \;` can't? – Tim Jun 08 '18 at 21:12
  • You’re right, I’ve amended my answer. – Stephen Kitt Jun 08 '18 at 21:15