In the previous post we introduced the Linux command line and, more specifically, the CLI Bash as a powerful tool that we must not be afraid to use when using a Linux-based system like Raspberry Pi.
We left out some more advanced aspects of the command line. In this post we will delve into some of these advanced concepts of Bash and the terminal that will allow us to be more efficient when running commands in Linux on our Raspberry Pi.
Sequential execution of commands
In Bash it is possible to execute several commands in a single line. So, if we want to execute command1 and then command2, regardless of the result of command1, we can use the separator ’;’
command1 ; command2
It is also possible to conditionally execute sequences of commands, where the execution depends on the result of the previous command.
So, to execute a command only if the previous command was successful, we use the separator ’&&’
command1 && command2
If, on the other hand, we want to execute a command only if the previous command failed, we use the separator ’||’
command1 || command2
As an example, to launch a 5-second wait and then launch the ‘nano’ text editor opening the ‘hello.txt’ file we execute the following instruction:
sleep 5 && nano hello.txt
Using Bash history
We have already seen in the previous post that we can navigate between previously entered commands using the “up” and “down” arrow keys on the keyboard.
We can also use reverse search by pressing the ‘Control + R’ keys. By typing the first letters of a command that we have previously written, Bash searches among the commands and finds the command that starts with the letters we have written.
Once located, we can press enter to execute the command, or tab to leave it as the current command.
On the other hand, if we want to repeat the last command used we can write
!!
For example, it is very useful if we have written a command and have forgotten to use sudo. We can repeat the command by typing:
sudo !!
Finally, it is also possible to refer to one or more arguments written in the last command.
!* #The previous command without the last word
!$ #The last word of the previous command
$* #All parameters from the previous command
$@ #All parameters from the previous command as a vector
For example, we can create a directory and then access it by typing:
mkdir veryLongDirectoryName
cd $*
A similar behavior can be obtained with the key combination ‘Alt + .,’ which cyclically shows the last entered arguments.
Using WildCards
It is possible to use the symbol ’*’ as a wildcard, meaning “anything”.
For example, if we have a file called ‘reallyLongFileName’ and we want to apply a command, we can use
command name*Long
We will execute the command on all files that start with name and end with long, within the current directory.
A very common use is to delete (or copy, or any other command) all files with an extension. For example, to delete all files with the ‘txt’ extension we would execute:
rm *.txt
Redirections in Bash
Another interesting aspect is the possibility of performing redirections, that is, making the output or input of a command have a different origin than the command line. The most common destinations/origins are text files (although there are others).
So, an output redirection, in which the result of a command is sent to a “destination” instead of being displayed on the screen, would look like this:
command > destination
And an input redirection, in which the command uses “origin” as input instead of the keyboard
command2 < origin
For example, if we want to save the result of a command in a text file we use an output redirection. To do this we use the ’>’ character if we want to replace the contents of the file, or ’>>’ if we want to add the content while keeping the original.
So, if we want to save the list of files and folders in a directory to an “output.txt” file we could execute the following instruction:
ls > output.txt
If, continuing with the example, we want to count the number of lines in the “output.txt” file we can use an input redirection with the following instruction:
wc < output.txt
Pipes
Pipes allow sending the result of a command as input to another command. It is similar to combining an output redirection and an input redirection. The ’|’ character is used for this.
For example, the following example lists all the files in a folder with the ‘ls’ command and then searches the result for lines containing the word ‘word’ with the ‘grep’ command.
ls | grep Word
Multiple command interpreters
In most distributions it is possible to execute several independent and simultaneous command interpreters, apart from those that we can launch as windows within the graphical environment.
So, we can press the key combination Control ‘Ctrl + Alt + F1’ … F6, to launch up to 6 independent terminals from the graphical environment.
If we have several terminals open, we can execute the following command to know in which terminal we are.
Tty
On the other hand, the keyboard shortcut ‘Ctrl + d’ closes the current terminal session. Finally, the combination ‘Ctrl + Alt + F7’ will return us to the graphical environment, if we were using one.
Running processes in parallel
It is also possible to run several processes in parallel from a single command line. To run a command and send it to the background we use the ’&’ character.
For example, if we want to launch chromium but not wait for it to close to continue running commands, we can launch it in the background with:
chromium &
On the other hand, the keyboard shortcut ‘Ctrl + z’ sends the current process to the background.
To see the processes we have running in the background we execute the command
bg
And to recover the last process we put in the background we use the command
fg
So far the post to become expert users of Bash and completely lose the fear. There are still many more things to explain, but we will discover them little by little. We will frequently use the command line in the Raspberry Pi and Linux tutorials. So you know. Let’s dive deeper into Bash!