3

How does the $1 work in this find command? I can't find any examples or documentation of what this is doing anywhere. This comes from a question 'Remove all file extensions in current working dir.'

find `pwd` -type f -exec bash -c 'mv "$1" "${1%.*}"' - '{}' \;
Stats4224
  • 778
  • 4
  • 13
  • Prefer `find $(pwd) -type f …` to ```find `pwd` -type f …``` for numerous reasons. Granted, in the present context, it doesn't matter much, but learning good habits now will benefit you when it does matter. – Jonathan Leffler Jan 29 '17 at 04:05
  • That's a great point! Thank you! – Stats4224 Jan 29 '17 at 04:07
  • 1
    Actually, prefer `find "$(pwd)" ...` to make sure the literal directory name is used instead of subjecting it to word-splitting or pathname expansion. – chepner Jan 29 '17 at 14:49

1 Answers1

7

The string to be executed by find is

bash -c 'mv "$1" "${1%.*}"' - '{}'

For each file it finds, find will replace {} with the pathname of the found file:

bash -c 'mv "$1" "${1%.*}"' - '/path/to/filename.ext'

bash then executes mv "$1" "${1%.*}" with $0 set to - (making it a login shell) and $1 set to /path/to/filename.ext. After applying the substitutions, this results in

mv /path/to/filename.ext /path/to/filename

Note: find `pwd` is a complicated way to say find ..

AlexP
  • 4,370
  • 15
  • 15
  • Got it. Thank you! I got so caught up in the exec that I didn't realize what the bash -c was doing. – Stats4224 Jan 29 '17 at 04:11
  • Does it really make it a login shell? I though `$0` in `bash -c` is just used as the name of the process. – Benjamin W. Jan 29 '17 at 05:01
  • @BenjaminW.: [`man bash`](http://manpages.ubuntu.com/manpages/zesty/en/man1/bash.1.html): "A login shell is one whose first character of argument zero is a `-`, or one started with the `--login` option". – AlexP Jan 29 '17 at 09:07
  • Note that the goal may or may not have been to actually create a login shell; it is common to simply put a dummy string as the first argument so that `$1` gets set correctly. Usually, you don't care what the value of `$0`. – chepner Jan 29 '17 at 14:47
  • I'm still not sure. Try this: `bash -c 'echo $0; shopt login_shell' -` - indicates that it's not a login shell. `bash --login -c 'echo $0; shopt login_shell' whatever` on the other hand _is_ a login shell, despite `$0` not starting with `-`. You can also put an `echo` statement into `.bash_profile` and see when it's executed: only with `--login`. The only time I see a login shell where `$0` actually is `-bash` is in the virtual console reachable with Ctrl+Alt+F1. – Benjamin W. Jan 29 '17 at 21:22
  • I guess the definitive answer is in the [source](http://git.savannah.gnu.org/cgit/bash.git/tree/shell.c). – Benjamin W. Jan 29 '17 at 21:58
  • so there are 3 ways: `{}`,`\`pwd\``, `pwd`. – loretoparisi Aug 01 '18 at 16:25