bash: how to update an associative array in an implicit subshell?

Since you have a complex command pipe you're reading from, you can use the following:

while read f; do
    # Do stuff
done < <(my | complex | command | pipe)

The syntax <(command) runs a command in a subshell and opens its stdout as a temporary file. You can use it any place where you would normally use a file in a command.

Further, you can also use the syntax >(command) to open stdin as a file instead.


If you are using bash 4.2, you can set the lastpipe shell option to allow the while loop, as the last element in the pipeline, to run in the current shell instead of a subshell.

A simple demonstration:

$ echo foo | read word
$ echo $word

$ set +m  # Only needed in an interactive shell to disable job control
$ shopt -s lastpipe
$ echo foo | read word
$ echo $word
foo

Is there a legitimate way to update an associative array form within a loop, or a subshell in general?

You could avoid a subshell by saying:

while read f; do
  ...
done < *.txt

That said, you sample code has problems otherwise. The loop would read the file line by line, so saying

wordcounts[$f]=$(wc -w  $f)

wouldn't really make much sense. You probably wanted to say:

wordcounts[$f]=$(wc -w <<< $f)

EDIT:

Alas, I seem to need the pipe ...

Quoting from the manual:

Each command in a pipeline is executed in its own subshell (see Command Execution Environment).