I want to create bash aliases within a loop where the loop is reading lines from a command. In order to read output line-by-line, I believe I need to pipe the output into read. When I do that, however, the aliases don’t exist.
If I include the following in my .bashrc:
for x in a1 a2; do
eval "alias $x='echo foo'"
done
echo -e "a3\na4" | while read x; do
eval "alias $x='echo foo'"
done
Aliases a1 and a2 exist, but a3 and a4 do not. What is the difference between those two loops?
The problem is the pipeline. In a pipeline of the form
a | b | c, each of the individual commandsa,b, andcis run in a separate subshell [ref], which means that it receives a copy of the parent’s execution environment (including aliases), and any changes it makes to its own copy (such as by runningalias) will have no effect on the parent [ref].In your case, you could fix this by writing:
which will still run
echo -e "a3\na4"in a subshell, but will run thewhile-loop in the normal/parent execution environment.