How well do you know bash?


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?

Answer
one

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 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?

Answer
I love UNIX!

Explanation
Some 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?

Answer
Just for fun

Explanation
There 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:
0one2
stdinstdoutstderr

bash detects the sequence 1>&2 and copies the contents of cell 2 into cell 1:
0one2
stdinstderrstderr

After finding the sequence 2>/dev/null interpreter writes the value to cell 2, leaving the other cells intact:
0one2
stdinstderr/ dev / null

bash also displays an error stream, so we don’t find the file text on the screen.

Task 4
How to send stdout output to stderr, and stderr output, on the contrary, to stdout?

Answer
4>&1 1>&2 2>&4

Explanation
The principle is exactly the same as in the previous problem. That is why we need an additional stream for temporary storage.

Executable files


Task 5

Given file test.sh

 #!/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 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 6

Create a file -c in the current directory with 755 rights and the following contents:

 #!/bin/bash echo $1 

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?

Answer
The first time will be displayed SURPRISE , the second time echo SURPRISE

Explanation
When 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?

Answer
The first will display the contents of the file file, the second will display the file name.

Explanation
In 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?

Answer
1234

Explanation
With 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?

Answer
If friendship is defined, then the contents of the variable. Otherwise - magic.

Explanation
In 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?

Answer
Nothing

Explanation
The 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?

Answer
2

Explanation
Add 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.

Source: https://habr.com/ru/post/413935/


All Articles