
Do you use command interpreter every day? Ready to solve a few logical problems and learn something new? Welcome under cat.
Part of the tasks presented here will not bring real benefits, as 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.
Note: at the time of this writing, the author 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?
ExplanationAfter 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 file that has already been cleared.
Task 2 $ cat file1 I love UNIX! $ cat file2 I don't like UNIX $ cat file1 <file2
What will be displayed on the screen?
ExplanationSome programs score on stdin when files are listed.
Task 3 $ cat file Just for fun $ cat file 1>&2 2>/dev/null
What will be displayed on the screen?
ExplanationThere is a misconception that the sequence
1>&2
redirects the first stream to the second, however, it is not. Consider the command from the task. At the beginning of the interpretation of the entered command, the flow table looks like this:
bash detects the sequence
1>&2
and copies the contents of cell 2 into cell 1:
After finding the sequence
2>/dev/null
interpreter writes the value to cell 2, leaving the other cells intact:
0 | one | 2 |
stdin | stderr | / dev / null |
bash also displays an error stream, so we don’t find the file text on the screen.
Task 4How to send stdout output to stderr, and stderr output, on the contrary, to stdout?
ExplanationThe principle is exactly the same as in the previous problem. That is why we need an additional stream for temporary storage.
Executable files
Task 5Given file test.sh
The following commands are executed:
$ ls 1 2 3 test.sh $ ./test.sh 1 2 3
What will the script output?
Answer1 2 3
1 2 3
ls: cannot access '1 2 3': No such file or directory
1 2 3
ExplanationWithout quotes, the variables $ * and $ @ are no different and are expanded to all the specified positional arguments of the script, separated by a space. In quotes, the disclosure mode changes: $ * turns into "$ 1 $ 2 $ 3", and $ @ in turn turns into "$ 1" "$ 2" "$ 3". Since there is no file “1 2 3” in the directory, ls displays an error
Task 6Create a file
-c
in the current directory with 755 rights and the following contents:
Let us reset the $ PATH variable and try to execute:
$ PATH= $ -c "echo SURPRISE"
What will be displayed on the screen? What happens if I repeat the last command?
AnswerThe first time will be displayed SURPRISE
, the second time echo SURPRISE
ExplanationWhen PATH is empty, the shell starts searching for files in the current directory. -c just is. Since the executable file is a text file, the first line is read for the subject. The team will be assembled according to the pattern:
<shebang> <filename> <args>
Thus, before execution, our team looks like this:
/bin/bash -c "echo SURPRISE"
And, as a result, what we wanted is not fulfilled at all.
If you execute the second time, the shell will select the information about -c from the cache and execute it correctly. The only way to protect against such an unexpected effect is to add two minuses to the shebang.
Variables
Task 7 $ ls file $ cat <$(ls) $ cat <(ls)
What will be displayed on the screen in the first and in the second case?
AnswerThe first will display the contents of the file file, the second will display the file name.
ExplanationIn the first case, the substitution is performed
cat <file
In the second case,
<(ls)
will be replaced by a named pipe connected by an input to stdout ls, and an output from stdin cat.
After substitution, the command will take the form:
cat /dev/fd/xx
Task 8 $ TEST=123456 $ echo ${TEST%56}
What will be displayed on the screen?
ExplanationWith such a record, the pattern is matched (# - from the beginning of the variable; ## - greedily from the beginning of the variable;% - from the end of the variable; %% - greedily from the end of the variable) and is deleted upon substitution. The contents of the variable remain untouched. Thus, for example, it is convenient to get the file name without an extension.
$ TEST=file.ext $ echo ${TEST%.ext} file
Task 9 $ echo ${friendship:-magic}
What will be displayed on the screen?
AnswerIf friendship is defined, then the contents of the variable. Otherwise - magic.
ExplanationIn documentation, this magic is called “unset or null” and allows you to use the specified default value of a variable in one line.
Execution order
Task 10 while true; false; do echo Success done
What will be displayed on the screen?
ExplanationThe while and if statements allow you to cram an entire sequence of actions into a condition, but the result (the return code) will only be taken into account in the last command. Since it is false there, the cycle will not even start.
Task 11 $ false && true || true && false && echo 1 || echo 2
What will be displayed on the screen?
ExplanationAdd parentheses for explicit order and simplify the command, taking into account that only the return code of the last command is taken into account:
((((false && true) || true) && false) && echo 1) || echo 2 (((false || true) && false) && echo 1) || echo 2 ((true && false) && echo 1) || echo 2 (false && echo 1) || echo 2 false || echo 2 echo 2
Comments, suggestions and additional tasks are welcome in the comments or drugs.