Check Yourself How Well Do You Know Bash?
Are you using the command shell every day?
And think you ready to solve some logical problems and learn something new?
Welcome to the quick quiz.
Part of the tasks presented here will not be of real use since it affects some complex boundary cases. The other part will be useful to those who constantly use the shell and read other people’s scripts.
Notes: at the time of writing we used bash 4.4.12 (1) -release in the Linux subsystem on Windows 10. The complexity of the tasks is different.
I/O Streams
Task 1
$ cat 1
The cake is a lie!
Wanted!
Cake or alive
$ cat 1 | head | tail | sed -e 's/alive/dead/g' | tee | wc -l > 1
How many lines will be in file 1 after executing the command?
Explanation
After interpreting the command, but before running all programs, bash works with the specified I/O streams. Thus, file 1 is cleared before running the first program and cat opens the already cleaned file.
Task 2
$ cat file1
I love UNIX!
$ cat file2
I don't like UNIX
$ cat file1 <file2
What will be displayed?
Explanation
Some programs are scrambled to stdin when the files are specified.
Task 3
$ cat file
Just for fun
$ cat file 1>&2 2>/dev/null
What will be displayed?
Explanation
There is a misconception that the sequence 1> & 2 redirects the first thread to the second one, however, it is not. Consider the command from the job. At the beginning of the interpretation of the entered command, the thread table looks like this: 0-stdin, 1-stdout, 2-stderr bash detects the sequence 1> & 2 and copies the contents of cell 2 to cell 1: After detecting the sequence 2> /dev/null, the interpreter writes the value to cell 2, leaving the other cells untouched: bash prints the same error stream, so that we find the text of the file on the screen.
Task 4
How to output stdout to stderr, and stderr, on the contrary, to stdout?
Explanation
The principle is exactly the same as in the previous problem. That’s why we need an additional stream for temporary storage.
Executables
Task 5
The file test.sh is given.
#!/bin/bash
ls $*
ls $@
ls "$*"
ls "$@"
The following commands are executed:
$ ls
1 2 3 test.sh
$ ./test.sh 1 2 3
What will the script output?
Answer
1 2 3 1 2 3 ls: cannot access ‘1 2 3’: No such file or directory 1 2 3
Explanation
Without quotes, the variables $ * and $ @ are no different and are expanded to all given positional arguments of the script, separated by a space. In quotes, the method of disclosure changes: $ * turns into “$ 1 $ 2 $ 3”, and $ @ in turn into “$ 1” “$ 2” “$ 3”. Since there is no “1 2 3” file in the directory, ls displays an error.
Task 6
Let’s create in the current directory a file -c with rights 755 and the following content:
#!/bin/bash
echo $1
Zero the $ PATH variable and try to execute:
$ PATH=
$ -c "echo SURPRISE"
What will be displayed? What happens if we repeat the input of the last command?
Answer
The first time will be displayed SURPRISE, the second time echo SURPRISE
Explanation
With empty PATH, the shell starts searching for files in the current directory. -c is just there. Since the executable file is a text file, the first line for the subject of the shebang is read. The team will collect by the template: Thus, before execution, our team looks like this: /bin/bash -c “echo SURPRISE” And, as a consequence, it is not what we wanted at all. If you run the second time, the shell will pick up information about -c from the cache and execute it already correctly. The only way to protect yourself from this unexpected effect is to add two minutes to the shebang.
Variables
Task 7
$ ls
file
$ cat <$(ls)
$ cat <(ls)
What will be displayed on the screen in the first and second cases?
Answer
The first will display the contents of the file, in the second – the file name.
After the substitution, the command will look like this:
Explanation
In the first case, the substitution is performed cat greater than a file. In the second case, greater than a (ls) will be replaced with a named pipe, connected by an input with stdout ls, and an output with stdin cat. After the substitution, the command will look like this: cat /dev/fd/xx
Task 8
$ TEST=123456
$ echo ${TEST%56}
What will be displayed?
Explanation
With this record, the pattern (# – from the beginning of the variable; ## – greedy from the beginning of the variable;% – from the end of the variable; %% – greedy from the end of the variable) and removed when the substitution. The content of the variable remains untouched. Thus, for example, it is convenient to obtain a file name without an extension.
Task 9
$ echo ${friendship:-magic}
What will be displayed?
Answer
If the variable friendship is defined, the contents of the variable. Otherwise, magic.
Explanation
In the documentation, this magic is called “unset or null” and allows you to use the specified default value of the variable in one line.
The order of implementation
Task 10
while true; false; do
echo Success
done
What will be displayed?
Explanation
The while and if statements allow a whole sequence of actions to be pushed into the condition, but the result (return code) will only be taken into account in the last command. Since there is false, the loop does not even begin.
Task 11
$ false && true || true && false && echo 1 || echo 2
What will be displayed?
Explanation
We add a bracket for the explicit order and simplify the command, taking into account that only the return code of the last command is taken into account:
We strongly recommend first to try it answer by yourself and then look at the answer and explanation.