Matty
Matty

Reputation: 175

The bash source command does not work with pipe

There are 3 files (a, b and c), all with 777 permissions:

$ ls
a  b  c

The above files have the following contents:

$ cat a
#!/bin/bash
export A=aaa
$ cat b
#!/bin/bash
source ./a
echo $A
$ cat c
#!/bin/bash
source ./a | >> log
echo $A

The only difference between b and c is | >> log:

$ diff b c
2c2
< source ./a
---
> source ./a | >> log

When b is executed it outputs the expected aaa:

$ ./b
aaa

When c is executed it outputs, for me, an unexpected blank row instead of the expected aaa, and the log file that script c created is empty:

$ ./c

$ cat log
$

Clearly, there is something about source and | that I have yet to learn.

Could someone please enlighten me regarding why c does not output aaa?

Upvotes: 0

Views: 1883

Answers (2)

wjandrea
wjandrea

Reputation: 32954

In Bash, the first command in a pipeline will always be executed in a subshell, so any variables that it imports are lost. But a pipeline is not what you want in the first place. With foo | >> file, it redirects the output of foo into a null command, then the output of the null command (which is null) is appended to the file. I'm not sure why Bash allows the second command in the pipeline to be null when there's a redirection.

You want command >> file, i.e.

$ cat c
#!/bin/bash
source ./a >> log
echo $A

Although source ./a doesn't produce any output.

Upvotes: 2

Charles Duffy
Charles Duffy

Reputation: 295373

Use a process substitution instead of a pipeline:

source ./a > >(tee -a log)

That way your source command runs in the original shell.

Alternately, stop creating a pipeline at all:

source ./a >>log

Upvotes: 7

Related Questions