In the following command I would like to know why $0 was evaluated to the file found by find and not the echo command.

$ find . -type f -perm -u=x -exec bash -c '
  /bin/echo $0 is the name of the file' {} \;

I know that if I had used double quotes, $0 would equal -bash and using single quotes delays the expansion, but why doesn't it expand to /bin/echo since that is the called command (which normally would be $0)?

  • 1
    I'd understand why you'd want $0 to expand to bash, but not echo. Do you expect rm "$0" to attempt to remove rm? See also unix.stackexchange.com/q/140779 and unix.stackexchange.com/q/152391 – Stéphane Chazelas May 12 '15 at 14:42
  • I don't want that behavior, I find this more useful, but I expected the behavior typically found when using $0 in a shell script where $0 represents the script itself. I was curious how it was working, not wishing it worked differently. – Gregg Leventhal May 12 '15 at 14:49

From the bash manual page:

 -c    If the -c option is present, then commands are read from the first 
       non-option argument command_string.  If there are arguments after 
       the command_string,  they are assigned to the positional 
       parameters, starting with $0.

The filename is given to bash as an argument using the braces {}, so it is assigned to $0. The expansion of $0 is then done by bash prior to calling /bin/echo.

  • 3
    As discussed here and here, some people like to insert a placeholder word between sh -c "(command)" and the argument list, if any, to straighten out this confusion.  For example, your command would become find . -type f … -exec bash -c '/bin/echo $1 is the name of the file' placeholder {} \;.  In the shell command, $0 would equal placeholder.  (It is common to use things like sh or _ as the placeholder.) – G-Man Says 'Reinstate Monica' May 12 '15 at 21:25

Not the answer you're looking for? Browse other questions tagged or ask your own question.