0

Is it possible to preserve environmental variables with find -exec? I don't see any options using the FreeBSD version of find. I can switch to a for loop if absolutely required, but was hoping to use the brevity of exec as well as it is faster.

The other option I can think of isn't pretty and that is dumping the environment and then reading it back in in the command I'm executing.

EDIT:

find . -type f -name '*/*.patch/go' -exec go install {} \;

In this example, I want go to use the http proxy. I already have code that tells git to configure a global http proxy (above this).

So, from the example below, I need to preface this with sh? Why?

3
  • I'm curious about the command that made you think the environment variables are not inherited. Or is it about a child process trying to alter the variables of the (grand)parent shell? Feb 15 at 7:20
  • "So, from the example below, I need to preface this with sh?" - for a counter example try FOO=bar find . -type f -exec awk 'BEGIN{print ENVIRON["FOO"]}' \; Feb 15 at 12:47
  • @they, you're right - I need to debug my scripts some more.
    – Walter
    Feb 19 at 3:00

1 Answer 1

4

Child processes always inherit the environment. This means that the utility that you launch from find ... -exec will have access to the environment.

Testing this:

$ unset -v myvar1 myvar2
$ export myvar1='hello world'
$ myvar2='not exported'
$ find . -exec sh -c 'for pathname do printf "found %s, myvar1=%s, myvar2=%s\n" "$pathname" "$myvar1" "$myvar2"; done' sh {} +
found ., myvar1=hello world, myvar2=
found ./.bash_profile, myvar1=hello world, myvar2=
found ./.bashrc, myvar1=hello world, myvar2=
found ./.yashrc, myvar1=hello world, myvar2=
found ./.zshrc, myvar1=hello world, myvar2=

Here I clear the two shell variables myvar1 and myvar2, then I set them and export myvar1 but not myvar2. This means myvar1 would be inherited by any child process while myvar2 would not be inherited.

As you can see in the output from find, the exported myvar1 is available inside the single-quoted sh -c script that find calls through -exec for batches of found pathnames.

You may also use an assignment in front of the find command to set the value of an environment variable without setting it in the current shell. This is standard syntax and not just how find works.

$ unset -v myvar1 myvar2
$ myvar2='now in environment' find . -exec sh -c 'for pathname do printf "found %s, myvar1=%s, myvar2=%s\n" "$pathname" "$myvar1" "$myvar2"; done' sh {} +
found ., myvar1=, myvar2=now in environment
found ./.bash_profile, myvar1=, myvar2=now in environment
found ./.bashrc, myvar1=, myvar2=now in environment
found ./.yashrc, myvar1=, myvar2=now in environment
found ./.zshrc, myvar1=, myvar2=now in environment

Another example of this syntax without using find:

$ unset -v x
$ x='hello there' sh -c 'printf "%s\n" "$x"'
hello there
$ printf "%s\n" "$x"

Note how x is not set in the current shell (the last printf outputs an empty line).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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