Bash is a fairly powerful programming language and easy to get to grips with. Here are some little-known but useful bash commands that will help make the shell scripts you write clearer and easier to maintain. After all, it’s almost always the shell you see when you open a terminal.

shell

There are some powerful commands in Bash that you may not be aware of, even if you are fairly proficient in the language. However, these commands are all very purposeful and can make the shell scripts you write clearer, easier to maintain and more powerful than ever before.

In this tutorial we will illustrate how the read, mapfile, and source commands can be used in practice in bash scripts. We give some common examples that we hope will be helpful.

The read command asks for user input

The read command allows a script to accept user input and store it in a variable.

1
2
3
4
#!/usr/bin/env bash
echo "What is your name?"
read name
echo "Your name is ${name}!"

This will wait for user input and then set the value of the name variable to the string entered by the user.

For example, if you specify myfreax.com as your name when running the above script, it will output Your name is myfreax.com.

You can also make the above example more elegant by specifying an option for the read command with -p, which will print the string -p specified after it, and then ask the user to enter.

1
2
3
#!/usr/bin/env bash
read -p "What is your name? " name
echo "Your name is ${name}!"

You will also notice that I have added a space after What is your name?. If we don’t add it, it will make the user look even stranger when typing.

The mapfile command converts the lines of a file into a Bash array

You can use the mapfile command to read the contents of a file and then assign the output to a Bash array, creating an array element whenever a newline is encountered in the file.

For example, we create a file called file.txt containing the following text.

1
2
3
4
5
Line 1
Line 2
Line 3
Line 4
Line 5

You can convert this file to a Bash array by running the following command, which assigns the contents of the file to the file_var variable.

1
2
3
4
5
6
#!/usr/bin/env bash
mapfile file_var < file.txt

for i in "${file_var[@]}"; do
	echo "${i}"
done

You will notice that the above also produces some oddly spaced output that does not match the contents of the file, which can be resolved by adding the -t option to the command.

1
2
3
4
5
6
#!/usr/bin/env bash
mapfile -t file_var < file.txt

for i in "${file_var[@]}"; do
	echo "${i}"
done

Finally, you may notice that the following does not work.

1
2
#!/usr/bin/env bash
cat file.txt | mapfile -t file_var

This is because the commands on the right-hand side of the mapfile pipe are executed in a subshell. In other words, it is run in a new instance of Bash, which cannot affect your current shell.

The source command imports the variables in the file into the shell’s environment variables

Suppose you have the following dummy file config.sh whose contents are as follows.

1
2
username=myfreax
domain=myfreax.com

If you want to get the contents of the file and put it into the environment variable of the current shell, this can be done very simply by using the source command

1
source config.sh

You can then check that the variables are assigned as expected. The source command actually runs the specified file in the environment of the current shell, so any commands in that file will be executed.

For example, let’s put the following into config.sh.

1
2
3
name="myfreax"
echo "Hello ${name}!"
echo "Have a good day!"

Then, if we run soure config.sh, you will see two echo commands get run, and the name variable is assigned: you can also use . instead of source, which does the same thing as source.

Conclusion

You learn how to use the read command to ask the user for input. How to use the mapfile command to convert the lines of a file into a Bash array. How the source command imports variables from a file into the shell’s environment variables. Also know the alias for the source command.