# bash scripting

* Leverage [ShellCheck.net](https://www.shellcheck.net/) and the [VS Code Addin](https://marketplace.visualstudio.com/items?itemName=timonwong.shellcheck)

## bash scripting

![bash logo](https://439978545-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDiEVTiIb6z0zL45wfNrM%2Fuploads%2Fgit-blob-f3b2057512dc2da2f3bf00e74c9ac879f4e69d9a%2Fbash-logo.svg?alt=media)

### Proper escaping - Everything is a string

#### Accessing values

{% code title="everything-is-a-string.sh" %}

```bash
#!/bin/bash

a="some string"

# this works, but I don't like it:
echo $a

# This is how I do it. Curly braces for string values:
echo "${a}"
```

{% endcode %}

#### Executing a command

{% code title="run-a-command.sh" %}

```bash
#!/bin/bash
# Running a command with backticks, but I don't like that:
fileContent=`cat 1.txt`

# Running a command with $( xxx )
fileContent="$( cat 1.txt )"
fileContent="$( echo "Hi" > 1.txt ; cat "./1.txt" ; rm ./1.txt )"
```

{% endcode %}

### Defining variables

#### Creating and accessing an array in bash

{% code title="array.sh" %}

```bash
#!/bin/bash
declare releaseNames=( "api-poi" "api-trip" "api-user" "api-user-java" )

echo "The array contains ${#releaseNames[@]} elements:"

for releaseName in "${releaseNames[@]}"; do
echo "  -  ${releaseName}"
done
```

{% endcode %}

#### Creating and accessing a hashmap / dict bash

```bash
declare -A helmValues
helmValues["a"]="val a"
helmValues["b"]="val b"

echo "a: '${helmValues["a"]}'"
echo "b: '${helmValues["b"]}'"
```

### Determine the directory of the script

{% code title="show:dir.sh" %}

```bash
#!/bin/bash
d="$( dirname "$( readlink -f "$0" )" )"
echo "Running in directory ${d}"
```

{% endcode %}

results in

```
$ pwd
/mnt/c/github/chgeuer/tips

$ ./show_dir.sh
Running in directory /mnt/c/github/chgeuer/tips
```

### Span a command across multiple lines

Use a baskslash (`\`) at the end of the line (no additional whitespace), and preferably indent the next line:

{% code title="multi-line.sh" %}

```bash
#!/bin/bash
response="$( cat payload.xml | curl \
  --silent --include \
  --request POST \
  --url "${triggerURI}" \
  --header "Content-Type: application/xml" \
  --data @- )"

echo "${response}"
```

{% endcode %}

### Lambda-style functions in bash

{% code title="health-probe.sh" %}

```bash
#!/bin/bash

#
# Define some function
#
function httpStatus {
  local url="$1"

  echo "$( curl \
  --silent \
  --output /dev/null \
  --write-out '%{http_code}' \
   "${url}" )"
}

function httpStatus2 { echo "$( curl --silent --output /dev/null --write-out '%{http_code}' $1 )" ; }

echo "Azure:    $( httpStatus "https://portal.azure.com/" )"
echo "Homepage: $( httpStatus2 "https://www.microsoft.com/" )"
```

{% endcode %}

results in

```bash
$ ./health-probe.sh
Azure:    200
Homepage: 200

$
```

### Creating a text file

The `cat > x <<-EOF ... EOF` syntax allows to create a file in the local directory. Please not that the lines 6 and 7 below (the content) are prefixed with a tabstop (), which does not show up in the actual text file.

```bash
#!/bin/bash

SERVER_IP="127.0.0.1"

cat > somefile.ini <<-EOF
	server=${SERVER_IP}
	port=5093
EOF
```

### base64-encode a text

The command `base64 --wrap=0` converts input into a long base64-encoded string without line breaks.

```bash
#!/bin/bash

FILE_CONTENT="$( cat ./foo.bin )"
ONE_LONG_BASE64_STR=$(echo "${FILE_CONTENT}" | base64 --wrap=0)
```

### Bash history

Put the following lines in `~/.inputrc`:

```
## arrow up
"\e[A":history-search-backward
## arrow down
"\e[B":history-search-forward
```
