In reality, all data sent (actually, written) to /dev/null will be discarded, but nonetheless generate a write operation succeeded back to the calling command. In this case, that would be the redirection.
This is important, because look what happens when a redirection is unable to complete successfully:
reader@ubuntu:~/scripts/chapter_12$ ./stderr &> /root/file
-bash: /root/file: Permission denied
reader@ubuntu:~/scripts/chapter_12$ echo $?
1
This operation fails (because the reader user obviously can't write in the home directory of the root superuser).
Look at what happens when we try the same thing with /dev/null:
reader@ubuntu:~/scripts/chapter_12$ ./stderr &> /dev/null
reader@ubuntu:~/scripts/chapter_12$ echo $?
0
reader@ubuntu:~/scripts/chapter_12$ cat /dev/null
reader@ubuntu:~/scripts/chapter_12$
That's all there is to it. All the output is gone (both stdout and stderr, because of the &> redirection), but the command still reports the desirable exit status of 0. When we make sure that the data is gone, we use cat /dev/null, which results in nothing.
We'll show you a practical example that you will no doubt find yourself using often in your scripting:
reader@ubuntu:~/scripts/chapter_12$ vim find.sh
reader@ubuntu:~/scripts/chapter_12$ cat find.sh
#!/bin/bash
#####################################
# Author: Sebastiaan Tammer
# Version: v1.0.0
# Date: 2018-11-06
# Description: Find a file.
# Usage: ./find.sh <file-name>
#####################################
# Check for the current number of arguments.
if [[ $# -ne 1 ]]; then
echo "Wrong number of arguments!"
echo "Usage: $0 <file-name>"
exit 1
fi
# Name of the file to search for.
file_name=$1
# Redirect all errors to /dev/null, so they don't clutter the terminal.
find / -name "${file_name}" 2> /dev/null
This script contains only constructs we've introduced before, apart from the /dev/null redirection of stderr. While this find.sh script is in fact nothing more than a simple wrapper around the find command, it makes a big difference.
Look at what happens when we use find to look for the file find.sh file (because why not!):
reader@ubuntu:~/scripts/chapter_12$ find / -name find.sh
find: ‘/etc/ssl/private’: Permission denied
find: ‘/etc/polkit-1/localauthority’: Permission denied
<SNIPPED>
find: ‘/sys/fs/pstore’: Permission denied
find: ‘/sys/fs/fuse/connections/48’: Permission denied
/home/reader/scripts/chapter_12/find.sh
find: ‘/data/devops-files’: Permission denied
find: ‘/data/dev-files’: Permission denied
<SNIPPED>
We've cut out about 95% of the output, since you would probably agree there isn't much merit in five pages of Permission denied errors. Because we're running find as a normal user, we do not have access to many parts of the system. These errors reflect this.
We did actually locate our script, as highlighted earlier, but it could take a few minutes of scrolling before you encounter it. This is exactly what we meant about error output drowning relevant output.
Now, let's look for the same file with our wrapper script:
reader@ubuntu:~/scripts/chapter_12$ bash find.sh find.sh
/home/reader/scripts/chapter_12/find.sh
There we go! Same result, but without all those pesky errors confusing us. Since the Permission denied errors are sent to the stderr stream, we deleted them using 2> /dev/null after the find command.
This actually brings us to another point: you can use redirection to silence commands as well. We've seen many commands that incorporate a --quiet or -q flag. Some commands, though, such as find, do not have this flag.
You could argue that it would be weird for find to have this flag (why search for files when you don't want to know where it is, right?), but there might be other commands in which exit codes present enough information, but do not have a --quiet flag; those are great candidates for redirection of everything to /dev/null.