Sub-Processing
Sub-Shells
A Subshell is an execution context similar to a sub-process, but is more optimized and lightweight
Than fork and exec system calls.
Caution
The sub-shell functions behave almost-identically to sub-processing, except that parent local variables do NOT need to be exported to be visible to a sub-shell
cd /tmp
# creating a file with 4 variable assignments
echo 'a=apples' > fruits.env
echo 'b=berries' >> fruits.env
echo 'c=carrots' >> fruits.env
echo 'd=durian' >> fruits.env
z=zebra
(
set -a
source fruits.env
set +a
bash -c 'printf "$a $b $c $d \n"'
# z doesn't need to be exported to be visible to the sub-shell
echo $z
# exporting z to make it available to a sub-process
export z
bash -c 'printf "$z\n"'
)
[[ $a || $b || $c || $d ]] || printf "variables not visible in the parent shell\n"
Bash Functions
There are two types of functions
Function executed in the current shell in the form of
function func_name(){command-list}Function executed in a sub-shell
function func_name()(command-list)
A function can be exported (exporting functions) with
export -f func_name
Here are two examples to illustrate the differences between the two types of functions
# not exported
a=apples
# shell PID
echo $BASHPID
function play(){
# same shell PID
echo $BASHPID
# local variables to the caller are visible
echo "a is $a"
b=berries
}
# execute the function
play
# local variables set within the function are visible to the caller
echo "b is $b"
The other type is executed in a sub-shell
function play()(
# different PID
echo $BASHPID
# parent-local variable is visible to the child
echo "a = $a"
# parent-exported variable is visible to the child
echo "z is $z"
# only available to the child and its children
export b=berries
# can provide return status
return 0
)
# not exported
a=apples
export z=zebra
# shell PID
echo $BASHPID
# this function call sees the two variables a=apples and z=zebra
play
[[ $? ]] && echo "last command status successful"
# child env variables cannot be seen by the parent process
[[ $b ]] || echo "variable b can never be visible to the parent"
# this call sees a different variable for a
a=apricot play
# but its value remains the same in the parent
echo $a
Passing Arguments
There are two mechanisms for passing arguments to a sub-process
positional arguments
Environment Variables
command line arguments involve the following special variables
$#the count of positional args starting of a function from 1$0zeroth positional param is the command with which the child process was executed$1first positional parameter passed as a command line argument, if it exists$*and$@expansion of positional arguments, starting from 1"$*"is equivalent to"$1 $2 ...""$@"is equivalent to"$1" "$2" ...
function printer()(
echo "count of passed arguments is: $#"
[[ $1 ]] && echo "the first argument is $1"
[[ $2 ]] && echo "the second argument is $2"
echo "all arguments are $@"
)
printer apples bananas
printer tigers