0

In my bashrc:

...
foo(){
 echo "foo";
}
export -f foo
...

and when I try to call that function from find -exec:

$ find . -exec sh -c 'cd "$1"; foo' sh {} \;

I got

sh: 1: foo: not found
sh: 1: foo: not found
sh: 1: foo: not found

so how to make the find command see the exported function?

milanHrabos
  • 2,010
  • 3
  • 11
  • 45
  • 1
    `dash: 5: export: Illegal option -f` it seems like you can't export functions in pure `sh`; you should use `find . -exec bash -c ...` instead – Fravadona Jun 06 '22 at 11:43
  • @Fravadona Then why is in almost every example of usage of `find -exec` used `sh`? I guess it is faster then bash? and starting bash for every file is time consuming? If so, is there any performance improvement? – milanHrabos Jun 06 '22 at 11:50
  • 1
    forking a `sh` is probably faster than forking a `bash`, but it's not guaranteed; the best way to speed up your script would be to reduce the number of forks with the construct `find . -exec bash -c 'for arg; do if pushd "$arg" > /dev/null; then foo; popd > /dev/null; done' _ {} +` – Fravadona Jun 06 '22 at 11:59
  • @Fravadona what are `pushd` abd `popd` and why do you call them in the bash string as functions? – milanHrabos Jun 06 '22 at 12:15
  • 1
    `pushd` is for `cd`ing somewhere, and `popd` is for returning where you where before the last successful `pushd`; they're bash builtins. – Fravadona Jun 06 '22 at 12:23
  • Most shells do not support exporting a function; that is unique to `bash`, as far as I know, and was the source of a rather nasty security hole a few years back. The function itself isn't really exported, just the *source* used to define it; a shell seeing such a definition in its environment redefines the function the same as if the definition were found in a configuration file. – chepner Jun 09 '22 at 13:56
  • `(cd "$arg" && foo)` might be simpler than using both `pushd` and `popd`, as long as a call to `foo` doesn't need to interact with the results of a previous call. – chepner Jun 09 '22 at 13:58
  • @Fravadona With a `fi;` before the `done;` the above `find` command works for me, but I'm wondering about the underscore `_`. If it is present the current working directory is included in the results, but how does it work? It is related to the underscore environment variable `$_`? – Stefan Schmidt Oct 18 '22 at 14:01
  • @StefanSchmidt in a script, `$0` should contain the command name and `"$@"` the arguments, but with `bash -c '…' arg1 arg2`, `arg1` won’t be in `"$@"` but in `"$0"` instead, so we use a dummy argument as a filler, for ex. `_` here – Fravadona Oct 18 '22 at 14:34
  • @Fravadona Ah, thanks for the concise explanation! I guess I was looking in the wrong places. The handling of positional parameters for `bash -c` is actually mentioned in the man page and the [Invoking Bash](https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Invoking-Bash) section of the Bash Reference Manual. – Stefan Schmidt Oct 18 '22 at 15:53

0 Answers0