Issue
I'm writing a shell script to run on a docker image based on Alpine. It's shell is /bin/sh
.
What I'm trying to do is execute a function for the results of a find
command. The following works in my local bash
and sh
shells.
myscript.sh:
#!/bin/sh
function get_tags {
# do stuff
}
export -f get_tags
# get all YAML files in ./assets/config that have 'FIND' somewhere in the filename
# pass each to the get_tags function
find ./assets/config -type f \( -iname "Find*.yaml" -or -iname "Find*.yml" \) -exec sh -c 'get_tags "$0"' {} \;
When I run it on the alpine image, however, I get the following error:
./myscript.sh: export: line 31: illegal option -f
Is there another way I can do this?
My question is NOT "what is the difference between sh
and bash
". My question is: how do I accomplish the task of running a function on the output of the find
command.
Solution
You need to use bash
, like this:
#!/bin/bash
fun() { echo "fun ${1}" ; }
export -f fun
find . -name 'foo' -exec bash -c 'fun "${1}"' -- {} \;
The key here is to run bash -c 'fun "${1}"' -- {} \;
. You can't call the function directly (and pass arguments to it). You need to wrap it into a minimal script where this minimal script receives the argument passed by find and passes it through to the function.
Note: I'm passing two arguments to bash -c
: the string --
and the actual filename {}
. I'm doing this by convention, because argument counting starts at $0
when a script is executed by bash -c
, in opposite to $1
when running a script the normal way (in a file, not via bash -c
)
bash -c 'fun "${0}"' {} \;
would work, but people might think $0
is the script name like they know it from normal scripts.
Answered By - hek2mgl Answer Checked By - Willingham (WPSolving Volunteer)