4

Normally you can set global variables inside bash functions.

But it seems not to be possible if the function is called by the pipe command. Is it possible to change this?

function myfunc()
{
    MYVAR=123
}

echo "hi" | myfunc
echo "MYVAR is $MYVAR" # $MYVAR  is not set. But why?
myfunc
echo "MYVAR is $MYVAR" # $MYVAR is now set as expected

Edit:

@Maroun wrote that piped functions are executed in a seperate process. But that cannot be as the following example shows:

#!/bin/bash
echo "main process is $$"

my_func ()
{
  echo "my_func is executed in process $$"
}

echo "hi" | my_func

Output:

main process is 3225
my_func is executed in process 3225

As you can see the process id is the same. Any ideas?

2
  • 1
    The problem is that you can't set global variables in a pipeline, as piped commands are executed in a subshell. There are many alternatives to a pipe for passing the data, where the function executes in the current environment. Commented Nov 21, 2021 at 12:40
  • A subshell starts with a copy of all the variables existing in the parent shell at the time it was launched. EDIT: a subshell isn't a process Commented Dec 4, 2021 at 10:13

2 Answers 2

5

If you really want to use a pipe, instead of other alternatives for passing data, it is possible to use the lastpipe option, which makes the last command in a pipeline execute in the current environment.

#!/bin/bash

myfunc () {
    var=foo
}

shopt -s lastpipe

echo something | myfunc
echo "$var"

Running this script will print foo.

It only works if myfunc is last in the pipeline.

It also only works if job control is not active, so it won't work if you try to test it in an interactive shell. Run it as a script.

Sign up to request clarification or add additional context in comments.

1 Comment

does this also means, that if there is a call to exit() inside myfunc(), then current script will also quit?
3

Check the documentation (Pipeline section):

Each command in a pipeline is executed as a separate process (i.e., in a subshell).

The variable MYVAR is not set since it's changed in a subshell that dies after the piped function has finished.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.