completes some more bash scripting
This commit is contained in:
parent
74fa7c957a
commit
83d38d2105
|
@ -1 +1,2 @@
|
|||
*.swp
|
||||
tmp.*
|
||||
|
|
|
@ -351,7 +351,6 @@ waldek@metal:~$
|
|||
|
||||
# Coding challenge - Output system stats
|
||||
|
||||
|
||||
Write a program that prints information about your computer such as:
|
||||
|
||||
* the hostname
|
||||
|
@ -410,6 +409,9 @@ hmmm, I don't know how to compare helloworld to supersecret
|
|||
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>
|
||||
<summary>Spoiler warning!</summary>
|
||||
|
||||
|
@ -425,11 +427,32 @@ echo "hmmm, I don't know how to compare $pass to $my_pass"
|
|||
|
||||
</details>
|
||||
|
||||
|
||||
|
||||
### `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
|
||||
|
||||
|
@ -457,14 +480,6 @@ This variable represents the *first* argument on the command line.
|
|||
Knowing this, what would `$4` mean?
|
||||
Indeed, the *fourth* argument...
|
||||
|
||||
## From a file
|
||||
|
||||
TODO
|
||||
|
||||
## From a pipe
|
||||
|
||||
TODO
|
||||
|
||||
# Coding Challenge - output the exact output below
|
||||
|
||||
```
|
||||
|
@ -900,14 +915,208 @@ fi
|
|||
|
||||
</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.
|
||||
|
||||
[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.
|
||||
|
||||
|
@ -923,6 +1132,7 @@ Rename all files in a folder with an prefix or postfix.
|
|||
|
||||
# User Interface - Make your scripts user friendly.
|
||||
|
||||
* `case` for command line arguments
|
||||
* [dialog tutorial](https://www.linuxjournal.com/article/2807)
|
||||
* [better dialog tutorial](https://linuxcommand.org/lc3_adv_dialog.php)
|
||||
* [Ryan's tutorials](https://ryanstutorials.net/bash-scripting-tutorial/bash-user-interfaces.php)
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue