
Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: March 18, 2024
The shell is the main entry point for all but the most obscure embedded Linux distributions. Even in the latter, we should be able to run instructions in some form or another. Further, one of the most universal interactive ways to execute commands is to type them in with a keyboard.
In this tutorial, we discuss interactively-typed shell commands and how to insert a manual newline in the middle of a command. First, we go over the difference between adding a newline and submitting a command. After that, we talk about automatic newline insertion based on syntax. Next, we explore techniques to interactively include a newline within a shell command. Then, we look at command-line editing. Finally, we perform a comparison between different methods of command newline insertion based on the environment.
We tested the code in this tutorial on Debian 12 (Bookworm) with GNU Bash 5.1.4. It should work in most POSIX-compliant environments unless otherwise specified.
Running a shell command usually involves two steps at the prompt:
Like other major operating systems, Linux uses a newline via the Return (Enter) key to trigger a line buffer submission.
Let’s see an example:
$ printf 'Line 1.\nLine2.\n'[Return]
Line 1.
Line 2.
$
In this case, we use printf for outputting two lines of text. To do so, we enter the command and press Return.
This special role of the newline might present challenges in the same way that filenames with newlines could. Also, sometimes we might want to have a newline as part of the buffer instead of its end and submission signal.
Naturally, most major shells can detect basic syntax interactively. Thus, unfinished surrounding constructs start another line instead of submitting the current buffer when Return is pressed:
$ printf 'Line 1.[Return]
> Line 2.[Return]
> '
Line 1.
Line 2.
$
In this case, a > right angle bracket and a space precede each continuation line, but they aren’t part of the final buffer contents when submitting. The prefix might be different for shells other than Bash. Critically, we can’t go back to a previous line from a line starting with >.
The mechanism above is valid for other structures as well:
Notably, the automatic line continuation usually doesn’t work for (square) brackets, since they are either just the [ (test) built-in (Bash) or excluded from the line syntax handling.
In contrast, a semi-automatic way of continuing a command on the next line without preserving the newlines is to escape the newline (Return) character. We do this by inserting a backslash at the end of a line like in this echo example without quotes:
$ echo Line 1.\[Return]
> Line 2.\[Return]
> [Return]
Line 1.Line 2.
In all cases above, we just visually format our command buffer but only preserve the newline characters when they’re within quotes.
Now, let’s see how to actually insert a newline by hand.
In most shells, we can use caret notation to both insert and display special characters and control sequences.
Notably, as long as the shell supports it, all options for inserting newlines that we look at below allow us to go back through the lines via the Left arrow key.
One of the available key combinations that are fairly universal involves the input of Ctrl+V followed by Ctrl+J:
$ echo Line 1.[Ctrl+V, Ctrl+J]
Line 2.[Ctrl+V, Ctrl+J]
Line 1.
[...]Line: command not found
$
Critically, the shell still considers the newline character as a command submission. Because of this, echo only works with Line 1., but Line 2. is seen as its own command and results in an error.
In fact, sh and dash even insert ^J, while [t]csh inserts ^M, all with the same combination. Upon submission of the buffer, ^J and ^M do add a newline to the output.
In other words, we can use Ctrl+V, Ctrl+J to create a script interactively in most shells.
There are two newline combinations specific to the Zsh shell that work just like Ctrl+V, Ctrl+J, which is also available in Zsh:
In most other shells, the combinations above produce and submit a ^[ control sequence inducer (CSI).
Still, we can get the same combinations to work in Bash by adding a line to $HOME/.inputrc:
$ cat $HOME/.inputrc
"\e\C-m": "\026\n"
Here, \026 is ^V (Ctrl+V), while \e is an escape character and \C is a control prefix.
After we modify $HOME/.inputrc, we can either restart the shell or use bind to load the current entries of the file:
$ bind -f $HOME/.inputrc
The latter option doesn’t remove old bindings.
The Bash and Korn shells in particular offer another feature that enables arbitrary edits and insertion of any command:
$ command[Ctrl+X, Ctrl+E]
By using the combination Ctrl+X, Ctrl+E, we tell Bash to perform two actions:
Once ready with any edits, we save our changes and exit the editor. At this point, Bash or Korn runs the temporary file with our command as a shell script and removes it.
Of course, we can add any number of newlines and apply formatting.
Often, we only consider a number of shells as major ones in the Linux ecosystem:
Thus, we can create a comparison table of the usual ways to insert a newline and what shell supports which methods:
+-----------------------------------------------------+
| | sh | csh | bash | dash | zsh | ksh |
|----------------+----+-----+------+------+-----+-----|
| Syntax detect | + | - | + | + | + | + |
|----------------+----+-----+------+------+-----+-----|
| Editor | - | - | + | - | - | + |
|----------------+----+-----+------+------+-----+-----|
| Ctrl+V, Ctrl+J | - | - | + | - | + | - |
|----------------+----+-----+------+------+-----+-----|
| Alt-Return | - | - | / | - | + | - |
|----------------+----+-----+------+------+-----+-----|
| Esc-Return | - | - | / | - | + | - |
+-----------------------------------------------------+
Here, a / slash means it’s not supported out-of-the-box but can be added without much effort.
In this article, we discussed ways to insert a newline in a shell command.
In conclusion, there are different methods we can leverage to add newlines interactively within commands, and they mainly depend on the shell in use.