Learn › Linux Foundations › Chaining
( ) - a hands-on Linux lab on a real virtual machine.
Group commands in a subshell with ( ): a temporary copy of your shell where a variable or a cd vanishes when the group ends. Prove the isolation with a before-and-after pwd pair, read the group's single exit code, and learn when to reach for ( ) instead of { }, all in the practice terminal.
You know cd moves you into another folder. By the end of this lesson you will run a line that contains a cd, watch it work perfectly, and end up exactly where you started. Not because it failed. Because you sent a copy of your shell to do the walking.
That trick has a name, the subshell, and it is written with parentheses ( ). It is how engineers make risky detours, a quick look in another folder, a throwaway variable, while guaranteeing their real shell comes back untouched.
The black boxes below are a practice terminal: a safe sandbox that only checks the one command each step teaches, so you cannot break anything. On the real machine at the end of the module, the mission drills these same moves for real.
Wrap commands in parentheses ( ) and they run in a subshell: a temporary copy of your shell. The copy starts out identical to yours, same folder, same variables. The commands inside run in the copy, not in your shell. When the closing ) arrives, the copy is thrown away, along with every change it made.
So the rule is one sentence: whatever happens inside ( ) stays inside ( ). Your folder, your variables, your prompt, all of it is safe.
Parentheses have meant "run these commands in their own child shell" since Stephen Bourne's original Unix shell in the 1970s. Bash keeps that behavior unchanged today.
The syntax is friendly: an opening (, the commands separated by the semicolon ; you met a few lessons ago, and a closing ). Spaces around the parentheses are optional.
Start with a harmless pair of echoes. Before you run this, decide: will both lines print, or does the group swallow them?
( echo a; echo b )
prompt: student@linuxcamp:~$ answer: ( echo a; echo b )|||(echo a; echo b) output: a b hint: Two echoes separated by a semicolon, wrapped in parentheses: ( echo a; echo b )
Both lines printed, a then b, exactly as if you had run the two echoes with a plain semicolon. Printed output always reaches your screen, copy or no copy. So far the parentheses look useless. The difference is not WHAT the group runs, it is WHERE: those commands ran inside a copy of your shell. The next drill catches the copy in the act.
You met variables in the Bash lessons: X=inside stores the text inside under the name X, and $X reads it back.
This line sets X inside a subshell and prints it from inside. Then, after the group has closed, it prints $X a second time from your real shell. Before you run it, decide: will the second print still say inside?
( X=inside; echo "inside subshell: X=$X" ); echo "outside subshell: X=$X"
prompt: student@linuxcamp:~$ answer: ( X=inside; echo "inside subshell: X=$X" ); echo "outside subshell: X=$X" output: inside subshell: X=inside outside subshell: X= hint: Type it exactly: ( X=inside; echo "inside subshell: X=$X" ); echo "outside subshell: X=$X"
Read the two lines against each other. Inside the group, X held inside. Outside, the same $X printed nothing: the line ends at X= with nothing after it. The copy held the value, the copy died at ), and the value died with it. Your real shell never had an X at all.
Now for the promise from the start: a cd that cannot move you. The proof takes three short moves. First, mark where you are standing. pwd prints your current folder, and on this machine home is always /home/student.
pwd
prompt: student@linuxcamp:~$ answer: pwd output: /home/student hint: Just the three letters, then Enter: pwd
There is a logs folder here. This line sends a subshell into it: the cd logs moves the copy, and the pwd right after prints where the COPY stands. Remember cd prints nothing when it works, so the pwd inside does the talking.
Before you run it, decide two things: what will the printed path end with, and where will YOU be when the line finishes?
( cd logs; pwd )
prompt: student@linuxcamp:~$ answer: ( cd logs; pwd )|||(cd logs; pwd) output: /home/student/logs hint: A cd and a pwd, separated by a semicolon, wrapped in parentheses: ( cd logs; pwd )
The copy reported from one level deeper: the path ends in /logs. The cd worked perfectly, inside the copy. And look at your prompt on the next line: still ~, your home. Do not take the prompt's word for it, though. Ask your own shell directly.
The subshell walked into logs, reported, and vanished. One more pwd, this time in your real shell:
pwd
prompt: student@linuxcamp:~$ answer: pwd output: /home/student hint: Same three letters as before: pwd
Put the three answers side by side. Before: /home/student. Inside the group: /home/student/logs. After: /home/student, identical to the first, character for character. That matching pair is the whole lesson: a successful cd ran, and you never moved. You have now caught the copy twice, once holding a variable, once holding a folder change. That is the entire trick, and it is yours.
Grouping has a second gift, and it connects straight back to your && and || lessons. Every command finishes by reporting a number called its exit code: 0 means it succeeded, any other number means it failed. That number is what && and || actually check. The full exit-code story has its own lesson coming soon; here you only need the zero-or-not rule.
A group reports exactly one exit code: the code of the last command inside it. Two helpers make that visible. The command false does nothing except fail on purpose. The marker $? holds the exit code of whatever ran last; it gets its own lesson soon too.
Before you run this, decide: what single digit will print?
( false ); echo $?
prompt: student@linuxcamp:~$ answer: ( false ); echo $?|||(false); echo $? output: 1 hint: A subshell holding only false, then a semicolon, then echo $?
1: the failure code of false, the last and only command inside the group. This is why grouping matters in chains. An && or || written after the closing ) reads that one number, so a single operator can pass judgment on a whole bundle of commands at once.
One relative deserves a mention before the challenges. Braces { } also group commands, but with the opposite habit: they run the commands in your CURRENT shell, so a variable or a cd inside them really sticks. They get the very next lesson to themselves.
Until then, one rule of thumb covers both: parentheses to wander off and come back clean, braces when you want the changes to stay.
Scaffolding off. No command is shown from here on.
Print the word a and then the word b, in that order, as a single grouped unit running in its own subshell, all on one line.
prompt: student@linuxcamp:~$ answer: ( echo a; echo b )|||(echo a; echo b) output: a b hint: The printing command you know best, twice, a semicolon between them, parentheses around them
Two words, one bundle, and your shell never noticed a thing. That is the shape you will reuse whenever several commands belong together but their side effects do not belong to you.
Without leaving home, get the full path of the logs folder printed from INSIDE it. One line: send in a subshell that walks into logs and asks where it stands.
prompt: student@linuxcamp:~$ answer: ( cd logs; pwd )|||(cd logs; pwd) output: /home/student/logs hint: The folder-changing command, then the where-am-I command, semicolon between, parentheses around
Now prove the scout came back alone and you are still home.
prompt: student@linuxcamp:~$ answer: pwd output: /home/student hint: The where-am-I command, on its own, in your real shell
The scout reported /home/student/logs; your own shell still says /home/student. You just used a subshell for exactly what it is for: gathering information from somewhere else without moving yourself.
Build a group whose only job is to fail, then print the verdict number it left behind. You met the always-fail command and the code-reading marker earlier this lesson.
prompt: student@linuxcamp:~$ answer: ( false ); echo $?|||(false); echo $? output: 1 hint: Wrap the always-fail command in parentheses, then echo the question-mark marker
1, the code of the last command inside the group. Three challenges, zero prompting. The parentheses are yours now.
You earned this cheat sheet. Every row is something you just ran in the practice terminal.
The one idea under all of it: parentheses run their contents in a temporary copy of your shell, so every change inside dies at ). And because a group reports a single exit code, one && or || after it can judge the whole bundle at once.
Reach for a subshell whenever a job needs a messy detour: cd somewhere, set throwaway variables, experiment freely, and return with your real shell exactly as you left it. When you WANT the changes to survive, that is the brace group { }, next lesson.
The practice terminal has walked you through the whole subshell story. Grouping commands with ( ), the variable that vanished, the cd that moved only the copy, the matching before-and-after pwd proof, and the single exit code a group reports. Every one of those you typed yourself and saw the real result.
The Chaining module ends with one real Linux machine: the chaining mission lab. There a VM boots just for you, and the mission hands you objectives built from these operators and groups, with no commands shown. You read the objective, recall the move, and type it. That recall is what makes it stick.
Finish the other Chaining lessons, then go run the relay for real.
Practice () Subshell Grouping in a real Linux terminal at The Linux Camp. Progress is verified automatically as you type commands on the machine.