Rename exercises dir

Name it instead "topics" so it won't be
strange if some topics included "exercises" directory.
This commit is contained in:
abregman
2022-08-02 01:51:39 +03:00
parent ea1d94d67b
commit 99c4e02ecf
235 changed files with 283 additions and 74 deletions

264
topics/shell/README.md Normal file
View File

@@ -0,0 +1,264 @@
## Shell Scripting
### Shell Scripting Exercises
|Name|Topic|Objective & Instructions|Solution|Comments|
|--------|--------|------|----|----|
|Hello World|Variables|[Exercise](hello_world.md)|[Solution](solutions/hello_world.md) | Basic
|Basic date|Variables|[Exercise](basic_date.md)|[Solution](solutions/basic_date.md) | Basic
|Great Day|Variables|[Exercise](great_day.md)|[Solution](solutions/great_day.md) | Basic
|Factors|Arithmetic|[Exercise](factors.md)|[Solution](solutions/factors.md) | Basic
|Argument Check|Conditionals|[Exercise](argument_check.md)|[Solution](solutions/argument_check.md) | Basic
|Files Size|For Loops|[Exercise](files_size.md)|[Solution](solutions/files_size.md) | Basic
|Count Chars|Input + While Loops|[Exercise](count_chars.md)|[Solution](solutions/count_chars.md) | Basic
|Sum|Functions|[Exercise](sum.md)|[Solution](solutions/sum.md) | Basic
|Number of Arguments|Case Statement|[Exercise](num_of_args.md)|[Solution](solutions/num_of_args.md) | Basic
|Empty Files|Misc|[Exercise](empty_files.md)|[Solution](solutions/empty_files.md) | Basic
|Directories Comparison|Misc|[Exercise](directories_comparison.md)| :( | Basic
|It's alive!|Misc|[Exercise](host_status.md)|[Solution](solutions/host_status.md) | Intermediate
## Shell Scripting - Self Assessment
<details>
<summary>What does this line in shell scripts means?: <code>#!/bin/bash</code></summary><br><b>
`#!/bin/bash` is She-bang
/bin/bash is the most common shell used as default shell for user login of the linux system. The shells name is an acronym for Bourne-again shell. Bash can execute the vast majority of scripts and thus is widely used because it has more features, is well developed and better syntax.
</b></details>
<details>
<summary>True or False? When a certain command/line fails in a shell script, the shell script, by default, will exit and stop running</summary><br><b>
Depends on the language and settings used.
If the script is a bash script then this statement is true. When a script written in Bash fails to run a certain command it will keep running and will execute all other commands mentioned after the command which failed.
Most of the time we might actually want the opposite to happen. In order to make Bash exist when a specific command fails, use 'set -e' in your script.
</b></details>
<details>
<summary>What do you tend to include in every script you write?</summary><br><b>
Few example:
* Comments on how to run it and/or what it does
* If a shell script, adding "set -e" since I want the script to exit if a certain command failed
You can have an entirely different answer. It's based only on your experience and preferences.
</b></details>
<details>
<summary>Today we have tools and technologies like Ansible, Puppet, Chef, ... Why would someone still use shell scripting?</summary><br><b>
* Speed
* Flexibility
* The module we need doesn't exist (perhaps a weak point because most CM technologies allow to use what is known as "shell" module)
* We are delivering the scripts to customers who don't have access to the public network and don't necessarily have Ansible installed on their systems.
</b></details>
#### Shell Scripting - Variables
<details>
<summary>How to define a variable with the value "Hello World"?</summary><br><b>
`HW="Hello World`
</b></details>
<details>
<summary>How to define a variable with the value of the current date?</summary><br><b>
`DATE=$(date)`
</b></details>
<details>
<summary>How to print the first argument passed to a script?</summary><br><b>
`echo $1`
</b></details>
<details>
<summary>Write a script to print "yay" unless an argument was passed and then print that argument</summary><br><b>
```
echo "${1:-yay}"
```
</b></details>
<details>
<summary>What would be the output of the following script?
```
#!/usr/bin/env bash
NINJA_TURTLE=Donatello
function the_best_ninja_turtle {
local NINJA_TURTLE=Michelangelo
echo $NINJA_TURTLE
}
NINJA_TURTLE=Raphael
the_best_ninja_turtle
```
</summary><br><b>
Michelangelo
</b></details>
<details>
<summary>Explain what would be the result of each command:
* <code>echo $0</code>
* <code>echo $?</code>
* <code>echo $$</code>
* <code>echo $#</code></summary><br><b>
</b></details>
<details>
<summary>What is <code>$@</code>?</summary><br><b>
</b></details>
<details>
<summary>What is difference between <code>$@</code> and <code>$*</code>?</summary><br><b>
`$@` is an array of all the arguments passed to the script
`$*` is a single string of all the arguments passed to the script
</b></details>
<details>
<summary>How do you get input from the user in shell scripts?</summary><br><b>
Using the keyword <code>read</code> so for example <code>read x</code> will wait for user input and will store it in the variable x.
</b></details>
<details>
<summary>How to compare variables length?</summary><br><b>
```
if [ ${#1} -ne ${#2} ]; then
...
```
</b></details>
#### Shell Scripting - Conditionals
<details>
<summary>Explain conditionals and demonstrate how to use them</summary><br><b>
</b></details>
<details>
<summary>In shell scripting, how to negate a conditional?</summary><br><b>
</b></details>
<details>
<summary>In shell scripting, how to check if a given argument is a number?</summary><br><b>
```
regex='^[0-9]+$'
if [[ ${var//*.} =~ $regex ]]; then
...
```
</b></details>
#### Shell Scripting - Arithmetic Operations
<details>
<summary>How to perform arithmetic operations on numbers?</summary><br><b>
One way: `$(( 1 + 2 ))`
Another way: `expr 1 + 2`
</b></details>
<details>
<summary>How to perform arithmetic operations on numbers?</summary><br><b>
</b></details>
<details>
<summary>How to check if a given number has 4 as a factor?</summary><br><b>
`if [ $(($1 % 4)) -eq 0 ]; then`
</b></details>
#### Shell Scripting - Loops
<details>
<summary>What is a loop? What types of loops are you familiar with?</summary><br><b>
</b></details>
<details>
<summary>Demonstrate how to use loops</summary><br><b>
</b></details>
#### Shell Scripting - Troubleshooting
<details>
<summary>How do you debug shell scripts?</summary><br><b>
Answer depends on the language you are using for writing your scripts. If Bash is used for example then:
* Adding -x to the script I'm running in Bash
* Old good way of adding echo statements
If Python, then using pdb is very useful.
</b></details>
<details>
<summary>Running the following bash script, we don't get 2 as a result, why?
```
x = 2
echo $x
```
</summary><br><b>
Should be `x=2`
</b></details>
#### Shell Scripting - Substring
<details>
<summary>How to extract everything after the last dot in a string?</summary><br><b>
`${var//*.}`
</b></details>
<details>
<summary>How to extract everything before the last dot in a string?</summary><br><b>
${var%.*}
</b></details>
#### Shell Scripting - Misc
<details>
<summary>Generate 8 digit random number</summary><br><b>
shuf -i 9999999-99999999 -n 1
</b></details>
<details>
<summary>Can you give an example to some Bash best practices?</summary><br><b>
</b></details>
<details>
<summary>What is the ternary operator? How do you use it in bash?</summary><br><b>
A short way of using if/else. An example:
[[ $a = 1 ]] && b="yes, equal" || b="nope"
</b></details>
<details>
<summary>What does the following code do and when would you use it?
<code>diff <(ls /tmp) <(ls /var/tmp)</code>
</summary><br>
It is called 'process substitution'. It provides a way to pass the output of a command to another command when using a pipe <code>|</code> is not possible. It can be used when a command does not support <code>STDIN</code> or you need the output of multiple commands.
https://superuser.com/a/1060002/167769
</details>
<details>
<summary>What are you using for testing shell scripts?</summary><br><b>
bats
</b></details>

View File

@@ -0,0 +1,23 @@
## Argument Check
### Objectives
Note: assume the script is executed with an argument
1. Write a script that will check if a given argument is the string "pizza"
1. If it's the string "pizza" print "with pineapple?"
2. If it's not the string "pizza" print "I want pizza!"
### Solution
```
/usr/bin/env bash
arg_value=${1:-default}
if [ $arg_value = "pizza" ]; then
echo "with pineapple?"
else
echo "I want pizza!"
fi
```

View File

@@ -0,0 +1,5 @@
## Basic Date
### Objectives
1. Write a script that will put the current date in a file called "the_date.txt"

View File

@@ -0,0 +1,11 @@
## Count Chars
### Objectives
1. Read input from the user until you get empty string
2. For each of the lines you read, count the number of characters and print it
### Constraints
1. You must use a while loop
2. Assume at least three lines of input

View File

@@ -0,0 +1,5 @@
## Directories Comparison
### Objectives
1. You are given two directories as arguments and the output should be any difference between the two directories

View File

@@ -0,0 +1,5 @@
## Empty Files
### Objectives
1. Write a script to remove all the empty files in a given directory (including nested directories)

9
topics/shell/factors.md Normal file
View File

@@ -0,0 +1,9 @@
## Shell Scripting - Factors
### Objectives
Write a script that when given a number, will:
* Check if the number has 2 as factor, if yes it will print "one factor"
* Check if the number has 3 as factor, if yes it will print "one factor...actually two!"
* If none of them (2 and 3) is a factor, print the number itself

View File

@@ -0,0 +1,7 @@
## Files Size
### Objectives
1. Print the name and size of every file and directory in current path
Note: use at least one for loop!

View File

@@ -0,0 +1,7 @@
## Great Day
### Objectives
1. Write a script that will print "Today is a great day!" unless it's given a day name and then it should print "Today is <given day>"
Note: no need to check whether the given argument is actually a valid day

View File

@@ -0,0 +1,6 @@
## Shell Scripting - Hello World
### Objectives
1. Define a variable with the string 'Hello World'
2. Print the value of the variable you've defined and redirect the output to the file "amazing_output.txt"

View File

@@ -0,0 +1,5 @@
## It's Alive!
### Objectives
1. Write a script to determine whether a given host is down or up

View File

@@ -0,0 +1,7 @@
## Number of Arguments
### Objectives
* Write a script that will print "Got it: <argument value>" in case of one argument
* In case no arguments were provided, it will print "Usage: ./<program name> <argument>"
* In case of more than one argument, print "hey hey...too many!"

View File

@@ -0,0 +1,9 @@
## Shell Scripting - Print Arguments
### Objectives
You should include everything mentioned here in one shell script
1. Print the first argument passed to the script
2. Print the number of arguments passed to the script
3.

View File

@@ -0,0 +1,13 @@
## Basic Date
### Objectives
1. Write a script that will put the current date in a file called "the_date.txt"
### Solution
```
#!/usr/bin/env bash
echo $(date) > the_date.txt
```

View File

@@ -0,0 +1,24 @@
## Count Chars
### Objectives
1. Read input from the user until you get empty string
2. For each of the lines you read, count the number of characters and print it
### Constraints
1. You must use a while loop
2. Assume at least three lines of input
### Solution
```
#!/usr/bin/env bash
echo -n "Please insert your input: "
while read line; do
echo -n "$line" | wc -c
echo -n "Please insert your input: "
done
```

View File

@@ -0,0 +1,30 @@
## Directories Comparison
### Objectives
1. You are given two directories as arguments and the output should be any difference between the two directories
### Solution
Suppose the name of the bash script is ```dirdiff.sh```
```
#!/bin/bash
if test $# -ne 2
then
echo -e "USAGE: ./dirdiff.sh directory1 directory2"
exit 1
fi
# check for the checksums.
# If both the checksums same, then both directories are same
if test `ls -1 $1 | sort | md5sum | awk -F " " '{print $1}'` == `ls -1 $2 | sort | md5sum | awk -F " " '{print $1}'`
then
echo -e "No difference between the 2 directories"
exit 0
fi
diff -q $1 $2
```

View File

@@ -0,0 +1,20 @@
## Empty Files
### Objectives
1. Write a script to remove all the empty files in a given directory (including nested directories)
### Solution
```
#! /bin/bash
for x in *
do
if [ -s $x ]
then
continue
else
rm -rf $x
fi
done
```

View File

@@ -0,0 +1,20 @@
## Shell Scripting - Factors
### Objectives
Write a script that when given a number, will:
* Check if the number has 2 as factor, if yes it will print "one factor"
* Check if the number has 3 as factor, if yes it will print "one factor...actually two!"
* If none of them (2 and 3) is a factor, print the number itself
### Solution
```
#!/usr/bin/env bash
(( $1 % 2 )) || res="one factor"
(( $1 % 3 )) || res+="...actually two!"
echo ${res:-$1}
```

View File

@@ -0,0 +1,17 @@
## Files Size
### Objectives
1. Print the name and size of every file and directory in current path
Note: use at least one for loop!
### Solution
```
#!/usr/bin/env bash
for i in $(ls -S1); do
echo $i: $(du -sh "$i" | cut -f1)
done
```

View File

@@ -0,0 +1,15 @@
## Great Day
### Objectives
1. Write a script that will print "Today is a great day!" unless it's given a day name and then it should print "Today is <given day>"
Note: no need to check whether the given argument is actually a valid day
### Solution
```
#!/usr/bin/env bash
echo "Today is ${1:-a great day!}"
```

View File

@@ -0,0 +1,15 @@
## Shell Scripting - Hello World
### Objectives
1. Define a variable with the string 'Hello World'
2. Print the value of the variable you've defined and redirect the output to the file "amazing_output.txt"
### Solution
```
#!/usr/bin/env bash
HW_STR="Hello World"
echo $HW_STR > amazing_output.txt
```

View File

@@ -0,0 +1,20 @@
## It's Alive!
### Objectives
1. Write a script to determine whether a given host is down or up
### Solution
```
#!/usr/bin/env bash
SERVERIP=<IP Address>
NOTIFYEMAIL=test@example.com
ping -c 3 $SERVERIP > /dev/null 2>&1
if [ $? -ne 0 ]
then
# Use mailer here:
mailx -s "Server $SERVERIP is down" -t "$NOTIFYEMAIL" < /dev/null
fi
```

View File

@@ -0,0 +1,26 @@
## Number of Arguments
### Objectives
* Write a script that will print "Got it: <argument value>" in case of one argument
* In case no arguments were provided, it will print "Usage: ./<program name> <argument>"
* In case of more than one argument, print "hey hey...too many!"
### Solution
```
#!/usr/bin/env bash
set -eu
main() {
case $# in
0) printf "%s" "Usage: ./<program name> <argument>"; return 1 ;;
1) printf "%s" "Got it: $1"; return 0 ;;
*) return 1 ;;
esac
}
main "$@"
```

View File

@@ -0,0 +1,30 @@
## Sum
### Objectives
1. Write a script that gets two numbers and prints their sum
3. Make sure the input is valid (= you got two numbers from the user)
2. Test the script by running and passing it two numbers as arguments
### Constraints
1. Use functions
### Solution
```
#!/usr/bin/env bash
re='^[0-9]+$'
if ! [[ $1 =~ $re && $2 =~ $re ]]; then
echo "Oh no...I need two numbers"
exit 2
fi
function sum {
echo $(( $1 + $2 ))
}
sum $1 $2
```

11
topics/shell/sum.md Normal file
View File

@@ -0,0 +1,11 @@
## Sum
### Objectives
1. Write a script that gets two numbers and prints their sum
3. Make sure the input is valid (= you got two numbers from the user)
2. Test the script by running and passing it two numbers as arguments
### Constraints
1. Use functions