Bash scripting introduction
Tags: bash, shell, productivity
Published: 2021-12-20 13:22:00

Bash scripting is a powerful tool. If you have been working on a UNIX based system, after quite some time, you end up working with it because you just realize that it exists for simplicity, efficiency and scalability. 

> One program's output shall be another one's input. 

That sums up how things are done and how you should think them too. Now before wanting to do anything fancy with bash scripting, there are already a lot of tools that boost your productivity and that I realized I was only using 10% of the actual power.
The aim of that article is to go through some of them, view some very useful tricks and hopefully, interest you in going further into that topic.

## Brace expansion
Brace expansion is a very useful tool to manipulate lists of "things". It is used in most cases to generate lists, files with redundant naming(s) etc... This tool allows you to save time and avoid mistakes because you do not need to type that much to generate those lists. 
Something worth noting about bash scripts is the fact that before the bash shell actually executes a command it will check whether it needs to perform any substitutions on the command. You probably used that with variables, or aliases before. Brace expansion is one of the multiple expansion forms that are supported by bash. Be wary, those expansions are not available in old shells. But most of current distros will allow you to use them.
Brace expansions are contained between a pair of `{}` braces. Inside of those will be comma-separated items or a range specifier.
The most common example could be done like that : 
```shell
echo {1,2,3,4,5}
```
This will output the values within the brackets. Do you get where this is going and how you can use that? Not yet? Look at this other example with a range this time:
```shell
# Will output all numbers from 1 to 10
echo {1..10}
# Will output all characters from A to Z and a to z
echo {A..z}
```
Now imagine you had the need to create 10 files with the same name but with a specific delimiter
```shell
touch filename{1..10}.txt
```
You are now able to create 10 files in one single command line.
## GREP
There is a handy tool called grep which lets you search files for specific patterns. 
Let's take a simple example and go ahead an create a simple log file.
```shell
ping google.com > /your/destination/output-logfile.log
```
Let that command run for a few seconds and kill the process. You should be left with a file with several lines in it.
Now if you would just want to read the file, you would run
```shell
cat /your/destination/output-logfile.log
```
But that would print out everything. What you want is to only view the line where the statistics are displayed. This is where grep comes in handy with something like this:
```shell
cat /your/destination/output-logfile.log | grep packets
```
Where the word packets is the word contained in one line I want to display. The output would be something like :
`7 packets transmitted, 7 received, 0% packet loss, time 6009ms`
Now this outputs us the whole line but we can actually format the output to only display what is interesting to us.
Let's imagine I only want to see the number of packets that were transmitted. This can be done by piping an additional command after the `grep`. Also, instead of creating a file and reading it with grep, we will be running grep directly on the running script :
```shell
ping -c 1 google.com | grep 'packets' | cut -d , -f 1
```
In this command we say :
* ping once google.com and give me the details
* only display the line with the word packets in it
* cut everything after the first delimiter ',' and only output the first group which leaves us with : 
`1 packets transmitted`

## Saving commands in script files
Now all of those shell tools are useful but sometimes they can get lengthy and this is exactly why script files exist. Most of the time you want to reuse those useful scripts you designed.
### Creating the file
Most script files for good notice start with 
`#!/bin/bash`. This is called the `she-bang(shabang)` which derives from the concatenation of the tokens sharp (#) and bang (!). This line is pretty important as it defines which shell is gonna interpret your script. `/bin/bash` is usually implemented as a symbolic link pointed to the executable of whichever shell is the system default shell.
You should probably always start your scripts also by some little documentation appending it to your `shabang`
```shell
#!/bin/bash
# This is a script to list apples
``` 
This way you can always come back to your script and actually understand what it was meant for without having to read the code in it.
Now our very simple script starts with 
```shell 
#!/bin/bash
# This is a script to list apples

echo "I have 3 apples"
```
Not super exciting is it?
Well we can try to add variables
```shell 
#!/bin/bash
# This is a script to list apples
a=Hello
b="Good Morning"
c=19
echo $a
echo $b
echo $c

echo "$b! I have $c apples"
```
Here your script has 3 variables defined that you can reuse by using the `$` sign before the variable name.
Now let's try to use that with our ping and grep command:
```shell 
#!/bin/bash
# This is a script to ping and view packets transmitted
a=$(ping -c 1 google.com | grep 'packets' | cut -d , -f 1)
echo $a
``` 
Now 2 in 1, we execute a child script in our script, store the value in our variable and echo the variable.

Now all of those examples are to demonstrate how shell can be powerful rather than actually explain how things can be done with existing Linux tools. If you want to dig deeper, remember that you can always type `man your tool` and you will be prompted with a full documentation or link to wherever you can find information on how to use your tool.