Why can't I go inside the while loop?

I want to create bash aliases in a loop where the loop reads lines from the command. To read the output in turn, I believe that I need to pass the output to read . However, when I do this, no aliases exist.

If I include the following in .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 these two cycles?

+6
source share
3 answers

The problem is the pipeline. In a pipeline of the form a | b | c a | b | c a | b | c , each of the individual commands a , b , and c is run in a separate subshell [ ref ], which means that it receives a copy of the parent execution environment (including aliases), and any changes it makes to its own copy ( such as by running alias ) will have no effect on the parent [ ref ].

In your case, you can fix this by writing:

 while read x; do eval "alias $x='echo foo'" done < <(echo -e "a3\na4") 

which will still run echo -e "a3\na4" in the subshell, but will run while -loop in the normal / parent runtime.

+5
source

The while loop in the pipe runs in a subshell. You can do:

 while read x; do eval "alias $x='echo foo'" done << EOF a3 a4 EOF 
+6
source

In bash 4.2 and later, you can set the lastpipe parameter lastpipe that the last channel command is executed in a subshell. Job control must also be turned off ( set +m ) for it to work.

 shopt -s lastpipe set +m echo -e "a3\na4" | while read x; do alias $x='echo foo' done 
+3
source

Source: https://habr.com/ru/post/923984/


All Articles