1. Overview
In this tutorial, we’ll look at various methods for running multi-line commands from a single command-line prompt.
2. Multi-Line Code Techniques
- Segmenting with a backslash at the end of the line
- Enclosing with parentheses
- Confining within curly braces
- Employing the EOF tag
- Using the double ampersand (&&) or semicolon (;) operator
- And most reliably, writing a script
Let’s look at each one in detail.
2.1. Using a Backslash
This is a useful technique that divides lengthy commands into readable statements contained within the shell session’s window.
Backslashes also break down command statements into understandable parts. Hence, they can be useful in breaking down a complex command into its individual operations. The backslash even allows us to execute multiple commands on multiple lines from a single prompt.
Let’s look at an example of using backslashes to segment a lengthy complex command:
$ find /etc -exec grep\
>'[0-9][0-9]*[.][0-9][0-9] \
> *[.][0-9][0-9]*[0-9][0-9]*' {} \;
2.2. Using Parentheses
These new variables cease to exist once the subshell has completed its execution. Consequently, even without a variable declaration, a subshell can run multiple commands from a single command prompt.
Let’s look at an example of a parenthesized subshell:
$ a=45
$ b=23
$ (
> c=`expr $a + $b`
> echo $c
> d=`expr $c + $a`
> echo $d
> )
68
113
$ echo $d
$ echo $c
$
We can see that the variables declared within the subshell are empty in the outer shell.
2.3. Using Curly Braces
Unlike parentheses, which start a subshell, curly braces run those commands within the current shell environment.
This means not only that the main shell session’s exported variables are accessible to the section in curly braces; the commands within the curly braces also export their variables to the main shell session:
$ a=60
$ b=45
$ {
> c=`expr $a + $b`
> echo $c
> d=`expr $c + $a`
> echo $d
> }
105
165
$ echo $c
105
$ echo $d
165
We can see that those variables declared within the curly braces are still active outside it.
2.4. Using the EOF tag
Note: We cannot assign values to variables in Here Tags, yet we can process imported variables.
Let’s look at an example:
$ a=50
$ b=60
$ sh << word
> echo "Equation: a + b = 110"
> echo $(($a + $b))
> echo ""
> echo "Inside Here Tag, Assignment c=110"
> c=`expr $a + $b`
> echo $c
> word
Equation: a + b = 110
110
Inside Here Tag, Assignment c=110
$ echo "Outside Here Tag, Assignment c=110"
$ echo $c
We see that the new variable c received no value despite processing the same arithmetic operation prior to it.
Historically, the default used text is EOF — an acronym for “End of File”, which suits such an activity. STOP is also widely used, though EOF is more popular and more descriptive.
We’re free to use any word, acronym, or syntax as the delimiter. However, sticking to either EOF or STOP is wiser. They are obvious to this method, and mistaking them for other commands is unlikely.
Let’s look at an example using an EOF (Here) tag, redirected to a Bash shell:
$ a=50
$ b=60
$ bash << EOF
> echo $(( $a + $b ))
> EOF
110
Let’s now look at the same example, but redirected to a Bourne shell:
$ a=50
$ b=60
$ sh << EOF
> echo $(( $a + $b ))
> EOF
110
We see that the syntax and results are the same.
2.5. Using Double Ampersand
The && operator is often used to adjoin tasks after a cd has been issued. Hence, the && operator is further beneficial in decreasing typing and streamlining our logic:
$ echo "The beginning of good things to come" > ThingsHeard.txt &&
> cat ThingsHeard.txt &&
> echo "Greater still, things to be done" >> ThingsHeard.txt &&
> cat ThingsHeard.txt &&
> cd txt &&
> echo "txt directory is non-existent" &&
> echo "These last two lines won't appear"
The Beginning of good things to come
The Beginning of good things to come
Greater still, things to be done
bash: cd: txt: No such file or directory
We see the subsequent commands remained unprocessed after encountering the erroneous statement.
2.6. Using Semicolons
$ cd doc ; cd txt ; echo "txt directory is non-existent" ; echo "sequential commands are not bothered"
bash: cd: txt: No such file or directory
txt directory is non-existent
sequential commands are not bothered
Note that all commands were executed despite the erroneous statement.
2.7. Combining Techniques
- The (&&) and (;) can execute a multi-line code that runs commands that are dependent and then independent of previous statements
- A subshell can include commands listed within curly braces or the EOF tag
- Curly braces could include a subshell and/or EOF tag
- The EOF tag can include subshells and curly braces
- A subshell can contain another subshell within it
- Curly braces could nest other curly braces
- The EOF tag could include other EOF tags
Also, let’s note there are some limitations, too:
- All other techniques can nest the backslash technique
- However, the backslash technique cannot nest other techniques within it except the double ampersand (&&)
- The Here tag (EOF) can only import variables from its most immediate shell session. Hence, if we’re nesting a Here tag inside curly braces, or a subshell, it will import variables from those sessions. It will not import from any other session prior, including the main shell session
Let’s look at an example of nested multi-line code:
$ a=20
$ b=15
$ {
> c=`expr $a + $b`
> echo $c
> echo -e "\nAn example of using the backslash \
> within curly braces as a nested multi-line code."
>
> (
> d=`expr $c + $a`
> echo $d
>
> sh << EOF
>
> echo $(($c + $b))
>
> cd txt &&
> echo -e "\n txt directory is non-existent, therefore, \
> this statement will not display."
>
> EOF
> )
>
> echo -e "\nSince the variable d was declared in a subshell \
> will it display outside the subshell? Let's see:"
>
> echo $d
>
> echo "No it didn't"
>
> echo -e "\nWill the variable e print? \
> It was nested inside a Here tag, inside \
> a sub shell."
>
> echo $e
>
> bash << EOF
>
> {
> cd doc &&
> echo "Greater still, the opportunities." >> ThingsHeard.txt &&
> cat ThingsHeard.txt
> (
> echo -e "\nA nested backslash statement \
> within a subshell, within curly braces."
>
> cd txt ;
>
> echo -e "\nEven though the directory txt is non-existent, \
> this statement will still print since the previous command \
> was separated with a semicolon (;)."
>
> )
> }
> EOF
> }
Let’s see the output from these commands:
35
An example of using the backslash within curly braces as a nested multi-line code.
55
50
sh: 5: cd: can't cd to txt
Since the variable d was declared in a subshell will it display outside the subshell? Let's see:
No it didn't
Will the variable e print? It was nested inside a Here tag, inside a sub shell.
The Beginning of good things to come
Greater still, the opportunities.
A nested backslash statement within a subshell, within curly braces.
bash: line 11: cd: txt: No such file or directory
Even though the directory txt is non-existent, this statement will still print since the previous command was separated with a semicolon (;).
2.8. Writing a Shell Script
Of course, we can use the previously mentioned techniques in a script. Let’s look at an example of a script containing multi-line code:
#!/bin/bash
#########################################
# This is a script that uses multi-line #
# code methods within it #
#########################################
a=$RANDOM
b=$RANDOM
{
c=`expr $a + $b`
echo $c
echo -e "\nA backslash multi-line code example \
within a script.\n"
(
d=`expr $c + $a`
echo $d
echo
cd doc &&
cat ThingsHeard.txt
echo
cd txt ;
echo -e "\n txt directory is non-existent \
yet the next command will still run because \
the semicolon is used as a separator.\n"
cat ThingsHeard.txt
)
bash << EOF
echo -e "\nA Here tag multi-line code example \
nested within curly braces, in a script."
EOF
}
Let’s look at an example of the above script called within curly braces:
${
> a=8
> b=9
> t=`expr $a + $b`
> echo $t
> echo
> ./multiline.sh
> }
Now, let’s see the resulting output:
17
37302
A backslash multi-line code example within a script.
53464
The Beginning of good things to come
Greater still, the opportunities.
./multiline.sh: line 31: cd: txt: No such file or directory
txt directory is non-existent yet the next command will still run because the semicolon is used as a separator.
The Beginning of good things to come
Greater still, the opportunities.
A Here tag multi-line code example nested within curly braces, in a script.
3. Conclusion
Linux is remarkable in the multiple ways it can execute a task or desired operation. This is certainly evident in the multiple ways a single command prompt can execute multi-line codes.
Copied from: https://www.baeldung.com/linux/run-multi-line-shell-code