completes some more bash scripting
This commit is contained in:
parent
74fa7c957a
commit
83d38d2105
|
@ -1 +1,2 @@
|
||||||
*.swp
|
*.swp
|
||||||
|
tmp.*
|
||||||
|
|
|
@ -351,7 +351,6 @@ waldek@metal:~$
|
||||||
|
|
||||||
# Coding challenge - Output system stats
|
# Coding challenge - Output system stats
|
||||||
|
|
||||||
|
|
||||||
Write a program that prints information about your computer such as:
|
Write a program that prints information about your computer such as:
|
||||||
|
|
||||||
* the hostname
|
* the hostname
|
||||||
|
@ -410,6 +409,9 @@ hmmm, I don't know how to compare helloworld to supersecret
|
||||||
waldek@metal:~$
|
waldek@metal:~$
|
||||||
```
|
```
|
||||||
|
|
||||||
|
We haven't learned how to *evaluate* values but if you're eager and quick you can try to figure it out yourself.
|
||||||
|
If not, no worries, we'll get to *conditional logic* soon enough.
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Spoiler warning!</summary>
|
<summary>Spoiler warning!</summary>
|
||||||
|
|
||||||
|
@ -425,11 +427,32 @@ echo "hmmm, I don't know how to compare $pass to $my_pass"
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### `read` multiple variables
|
### `read` multiple variables
|
||||||
|
|
||||||
TODO
|
`read` can be used to unpack multiple values right on the spot!
|
||||||
|
By *unpacking* I mean that each value is separated by **white space**.
|
||||||
|
A demonstration can be seen below, plus the actual code right after.
|
||||||
|
|
||||||
|
```
|
||||||
|
waldek@debian:~$ bash test.sh
|
||||||
|
first and last name please: wouter gordts
|
||||||
|
hello mr gordts...
|
||||||
|
or may I call you wouter?
|
||||||
|
waldek@debian:~$
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
read -p "first and last name please: " first last
|
||||||
|
echo "hello mr $last..."
|
||||||
|
echo "or may I call you $first?"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Exercise - unpack values
|
||||||
|
|
||||||
|
It is worth discovering what happens when you supply too many or to little values.
|
||||||
|
Please try this out!
|
||||||
|
|
||||||
## With command line arguments
|
## With command line arguments
|
||||||
|
|
||||||
|
@ -457,14 +480,6 @@ This variable represents the *first* argument on the command line.
|
||||||
Knowing this, what would `$4` mean?
|
Knowing this, what would `$4` mean?
|
||||||
Indeed, the *fourth* argument...
|
Indeed, the *fourth* argument...
|
||||||
|
|
||||||
## From a file
|
|
||||||
|
|
||||||
TODO
|
|
||||||
|
|
||||||
## From a pipe
|
|
||||||
|
|
||||||
TODO
|
|
||||||
|
|
||||||
# Coding Challenge - output the exact output below
|
# Coding Challenge - output the exact output below
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -900,14 +915,208 @@ fi
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
# Coding challenge - pipe or argument?
|
||||||
|
|
||||||
|
Can you code me a script that depending on how it is called, with argument or via pipe, prints a different message?
|
||||||
|
Along these lines...
|
||||||
|
|
||||||
|
```
|
||||||
|
waldek@debian:~$ bash test.sh
|
||||||
|
No input was found on stdin, skipping!
|
||||||
|
No input given!
|
||||||
|
waldek@debian:~$ bash test.sh shopping.list
|
||||||
|
No input was found on stdin, skipping!
|
||||||
|
Filename specified: shopping.list
|
||||||
|
Doing things now..
|
||||||
|
waldek@debian:~$ cat shopping.list | bash test.sh
|
||||||
|
Data was piped to this script!
|
||||||
|
waldek@debian:~$
|
||||||
|
```
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Spoiler warning!</summary>
|
||||||
|
|
||||||
|
**It might take you some time but we've seen all the necessary building blocks!**
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Spoiler warning!</summary>
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ -p /dev/stdin ]; then
|
||||||
|
echo "Data was piped to this script!"
|
||||||
|
else
|
||||||
|
echo "No input was found on stdin, skipping!"
|
||||||
|
if [ -f "$1" ]; then
|
||||||
|
echo "Filename specified: ${1}"
|
||||||
|
echo "Doing things now.."
|
||||||
|
else
|
||||||
|
echo "No input given!"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
# Loops - A variety of ways to perform repetitive tasks.
|
# Loops - A variety of ways to perform repetitive tasks.
|
||||||
|
|
||||||
[Ryan's tutorials](https://ryanstutorials.net/bash-scripting-tutorial/bash-loops.php)
|
Up until now all our scripts run from top to bottom, executing each line as they are read.
|
||||||
|
Most, if not all, programming languages offer some form of looping to **repeat** lines of code either based on a **condition** or for a predefined number of *items*.
|
||||||
|
|
||||||
Write a script that sets all you cpu's to a desired governor.
|
## `while` loop
|
||||||
|
|
||||||
Rename all files in a folder with an prefix or postfix.
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
counter=0
|
||||||
|
|
||||||
|
while [[ counter -lt 10 ]]; do
|
||||||
|
echo $counter
|
||||||
|
(( counter++ ))
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
### Read from a file with a `while` loop
|
||||||
|
|
||||||
|
Below you can see I have two files, one is my *shopping list*, the other my script.
|
||||||
|
The script loops over each item I have to buy and prints me a verbose message.
|
||||||
|
|
||||||
|
```
|
||||||
|
waldek@debian:~$ cat shopping.list
|
||||||
|
6 eggs
|
||||||
|
1 bread
|
||||||
|
2 milk
|
||||||
|
4 pasta
|
||||||
|
waldek@debian:~$ bash test.sh shopping.list
|
||||||
|
you need to buy: 6 eggs
|
||||||
|
you need to buy: 1 bread
|
||||||
|
you need to buy: 2 milk
|
||||||
|
you need to buy: 4 pasta
|
||||||
|
waldek@debian:~$
|
||||||
|
```
|
||||||
|
|
||||||
|
One way to do this is with a `while` loop.
|
||||||
|
The syntax is a follows.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
while read line; do
|
||||||
|
echo "you need to buy: $line"
|
||||||
|
done < $1
|
||||||
|
```
|
||||||
|
|
||||||
|
The syntax is not what I would call *pretty* but it is quite effective.
|
||||||
|
The **file** `$1` is redirected **into** the `while` loop which performs a `read`.
|
||||||
|
**When** there are no more lines in the file, the condition **fails** and the loop exits.
|
||||||
|
|
||||||
|
### Read from a pipe with a `while` loop
|
||||||
|
|
||||||
|
We can use a *very* similar construct to read data from a pipe.
|
||||||
|
The utilisation is as follows.
|
||||||
|
|
||||||
|
```
|
||||||
|
waldek@debian:~$ cat shopping.list | ./test.sh
|
||||||
|
you need to buy: 6 eggs
|
||||||
|
you need to buy: 1 bread
|
||||||
|
you need to buy: 2 milk
|
||||||
|
you need to buy: 4 pasta
|
||||||
|
waldek@debian:~$
|
||||||
|
```
|
||||||
|
|
||||||
|
And the code that does this as such.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
while IFS= read line; do
|
||||||
|
echo "you need to buy: $line"
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
What on earth is this `IFS=`?
|
||||||
|
I'm glad you [asked](https://unix.stackexchange.com/questions/184863/what-is-the-meaning-of-ifs-n-in-bash-scripting)!
|
||||||
|
|
||||||
|
## `for` loop
|
||||||
|
|
||||||
|
Ah, my favorite loop!
|
||||||
|
While the `while` loop runs as long as a condition is `true`, the `for` loop **iterates** over *items*.
|
||||||
|
The simplest way to visualize it would be as follows.
|
||||||
|
For each *friend* in my list of friends I'll say hello.
|
||||||
|
|
||||||
|
```
|
||||||
|
waldek@debian:~$ ./test.sh
|
||||||
|
these are my friends: adam camille alice bob steve
|
||||||
|
hello adam!
|
||||||
|
hello camille!
|
||||||
|
hello alice!
|
||||||
|
hello bob!
|
||||||
|
hello steve!
|
||||||
|
waldek@debian:~$
|
||||||
|
```
|
||||||
|
|
||||||
|
The syntax to achieve this goes as follows.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
friends="adam camille alice bob steve"
|
||||||
|
echo "these are my friends: $friends"
|
||||||
|
for f in $friends; do
|
||||||
|
echo "hello $f!"
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
### Counter loops with `for`
|
||||||
|
|
||||||
|
We can do a counter loop as well via a `for` loop.
|
||||||
|
An easy way to do this is by using the `seq` program.
|
||||||
|
Remember to read the `man seq` for more information.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
for number in $(seq 0 10); do
|
||||||
|
echo "number is $number"
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
### Finicky behaviour
|
||||||
|
|
||||||
|
`bash` is not the prettiest language and the difference between single and double quotes can be a bit confusing.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
for animal in dog cat horse 'racing horse' whale; do
|
||||||
|
echo "$animal says: I'm an animal..."
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
Which gives the following output.
|
||||||
|
|
||||||
|
```
|
||||||
|
waldek@debian:~$ ./test.sh
|
||||||
|
dog says: I'm an animal...
|
||||||
|
cat says: I'm an animal...
|
||||||
|
horse says: I'm an animal...
|
||||||
|
racing horse says: I'm an animal...
|
||||||
|
whale says: I'm an animal...
|
||||||
|
waldek@debian:~$
|
||||||
|
```
|
||||||
|
|
||||||
|
# Coding challenge - pipe or argument plus action!
|
||||||
|
|
||||||
|
Can you expand the previous coding challenge, where you perform a conditional logic on the input of the script and actually *use* the incoming data?
|
||||||
|
|
||||||
|
# Coding challenge - Rename files
|
||||||
|
|
||||||
|
Rename all files from [this](../assets/simple_sort_01.tar.gz) file with an prefix or postfix.
|
||||||
|
Can you give the files that start with an **uppercase** letter a different pre or postfix?
|
||||||
|
Can you move the files with lowercase into a different folder?
|
||||||
|
|
||||||
# Functions - Reuse code to make life easier.
|
# Functions - Reuse code to make life easier.
|
||||||
|
|
||||||
|
@ -923,6 +1132,7 @@ Rename all files in a folder with an prefix or postfix.
|
||||||
|
|
||||||
# User Interface - Make your scripts user friendly.
|
# User Interface - Make your scripts user friendly.
|
||||||
|
|
||||||
|
* `case` for command line arguments
|
||||||
* [dialog tutorial](https://www.linuxjournal.com/article/2807)
|
* [dialog tutorial](https://www.linuxjournal.com/article/2807)
|
||||||
* [better dialog tutorial](https://linuxcommand.org/lc3_adv_dialog.php)
|
* [better dialog tutorial](https://linuxcommand.org/lc3_adv_dialog.php)
|
||||||
* [Ryan's tutorials](https://ryanstutorials.net/bash-scripting-tutorial/bash-user-interfaces.php)
|
* [Ryan's tutorials](https://ryanstutorials.net/bash-scripting-tutorial/bash-user-interfaces.php)
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue