When to Use exec, source, or fork in Bash? A Practical Guide
This article explains the differences between exec, source, and fork in Bash, covering process creation, environment variable inheritance, command groups, variable substitution, positional parameters, logical operators, and provides example scripts to illustrate each concept for effective shell scripting.
Question 6: What is the difference between exec and source?
Question 7: What is the difference between ( ) and { }?
Question 8: What is the difference between (()), ( ), and ${ }?
Question 9: What is the difference between @ and *?
Question 10: What is the difference between && and ||?
This article is compiled from a 2003 CU post that collected useful Linux fundamentals.
Question 6: What is the difference between exec and source?
Consider the example where a script changes directory with cd /etc/aa/bb/cc but the change does not persist after the script finishes. This is because each script runs in a subshell, a child process created by the parent shell. When the child process ends, its environment (including the working directory) is not inherited back by the parent.
Environment variables are inherited only from parent to child, not the other way around. Therefore, a script executed via a subshell cannot modify the parent shell's environment.
The source command runs a script in the current shell without creating a subshell, so any changes to variables or the working directory affect the current environment.
Example: ./my.script can be changed to: source ./my.script or simply: ../my.script Using exec replaces the current process with the new command, terminating the original process. This is the main difference from source and a subshell.
Example scripts to illustrate the three behaviors:
#!/bin/bash
A=B
export A
echo "PID for 1.sh before exec/source/fork:$$"
case $1 in
exec)
echo "using exec…"
exec ./2.sh;;
source)
echo "using source…"
source ./2.sh;;
*)
echo "using fork by default…"
./2.sh;;
esac
echo "PID for 1.sh after exec/source/fork:$$" #!/bin/bash
echo "PID for 2.sh: $$"
echo "2.sh get A=$A from 1.sh"
A=C
export A
echo "2.sh: A is $A"Run the scripts with ./1.sh fork, ./1.sh source, and ./1.sh exec to observe the different outputs.
Question 7: What is the difference between ( ) and { }?
( ) creates a subshell for the command group, while { } executes the commands in the current shell. Use ( ) when you want temporary changes that should not affect the parent shell, and { } when you want changes to persist.
In Bash, a function can be defined using either syntax:
function function_name {
command1
command2
} function_name() {
command1
command2
}Functions behave like scripts but run in the current shell, allowing reuse of code without spawning new processes.
Question 8: What is the difference between (()), ( ), and ${ }?
$( )and backticks perform command substitution, inserting the output of a command into another command line. ${ } is used for variable substitution and provides additional features such as default values, substring removal, and length calculation.
Examples of variable manipulation with ${ }:
file=/dir1/dir2/dir3/my.file.txt
${file#*/} # dir1/dir2/dir3/my.file.txt
${file##*/} # my.file.txt
${file%/*} # /dir1/dir2/dir3
${#file} # 27 (length)Arrays can be defined and accessed:
A=(a b c def)
${A[@]} # a b c def
${A[0]} # a
${#A[@]} # 4Arithmetic expansion uses $(( )) for integer calculations:
a=5;b=7;c=2
echo $((a+b*c)) # 19
echo $(((a+b)/c)) # 6Question 9: What is the difference between $@ and $*?
Both represent all positional parameters, but when quoted they behave differently. "$@" expands to each parameter as a separate word, preserving spaces, while "$*" expands to a single word with all parameters concatenated.
Example:
#!/bin/bash
echo "the number of parameters in \"$@\" is "$(my_fun "$@")
echo "the number of parameters in \"$*\" is "$(my_fun "$*")Question 10: What is the difference between && and ||?
These logical operators chain commands based on return values. command1 && command2 runs command2 only if command1 succeeds (return value 0). command1 || command2 runs command2 only if command1 fails (non‑zero return value).
Example:
A=123
[ -n "$A" ] && echo "yes! it's true."
unset A
[ -n "$A" ] || echo "no, it's NOT true."These concepts are essential for writing robust Bash scripts that react to success or failure of commands.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
MaGe Linux Operations
Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
