---
# System prepended metadata

title: Bash / Bash Script

---

# Bash / Bash Script
## Waht is Shell
A **Shell** is a command interpreter. 
Commands can be executable files or built-ins. 
## What is Shell Script
A **Shell Script** is a plain text file containing a set of various commands.
It can be used to automate repetitive tasks on Linux filesystem. 


## What is Bash
Bash is a common and popular shell.

## shebang
``` bash 
#!/bin/bash
```

Specify the location of the shell interpreter in our operating system.
- on the first line
- no any space

## echo
``` bash
echo [option] [string]
```

Display the standard output by passing the arguments.

## Comment
### Single Line Comment
``` bash
# This is a single-line comment in Bash Script.  
```

### Multi Line Comment
``` bash
<<COMMENTS
COMMENTS

: '
'

<<COMMENTS
This is a 
multi-line comment 
in Bash Script.  
COMMENTS

: '
This is also a 
multi-line comment 
in Bash Script.
'
```

## Quote
Used to handle texts and filenames with a space character.
- content within the quotes should be considered as a single item
- shell variable expansion will only work with double-quotes.

``` bash
#!/bin/bash 
  
name="asdf"  
  
echo "$name"  
echo '$name' 
```


> asdf
> $name

## Variable
``` bash
name=Joey
echo $name
```
The containers which store data.
- case sensitive
- untyped
- no need of using any quotes to define a variable with single character value 
- no whitespace when doing assignment

### System-Defined Variables
``` bash
echo $HOME
echo $PWD
```

- BASH - shell name
- BASH_VERSION - shell version
- HOME - home directory
- PWD - current working directory


## Command Line Arguments
``` 
./script.sh arg1 arg2 arg3
```

- $0 - the name of the script
- $1~$9 - the first 9 arguments 
- $# - number of arguments
- $* - all arguments (as one word)
- $@ -  all arguments (as array)

``` bash
echo $1 $2
```

## Command Substitution
``` bash
var=$(command_name)
echo $var

var=`command_name`
echo $var
```

It takes the output of the Bash command, stores in a variable, and display back with echo.

## Read User Input
``` bash
read variable_name
read -p "name:" variable_name  # same prompt
read -sp "passward:" variable_name # silent mode
read -a array_name # read an array

```

## Arithmetic Operations
``` bash
Sum=$((10 + 3))
((Sum=10 + 3))
```

### Operators
- \+
- \-
- \*
- \/
- \*\*
- \%
- \+=
- \-=
- \*=
- \/=
- \%=

### Let
Perform arithmetic operations

```
let "z=$((10 + 3))"
```

### Backticks
Similar to "let", but it does not save the result to a variable. 

``` bash
`expr $a + $b`
```

## If
```
test condition
[condition]
[[condition]]
```


``` bash
if [ condition ]
then
statements
fi


if [ condition ];
then
statements
else
statements
fi

if [ condition ];  
then  
statements
elif [ condition ];  
then  
statements
else  
statements
fi  

```

### Operators
- !EXPRESSION - check if EXPRESSION is false
- \-n STRING - check if the length of STRING is greater than zero
- \-z STRING - check if the length of STRING is zero
- STRING1 == STRING2
- STRING1 != STRING2
- INTEGER1 -eq INTEGER2
- INTEGER1 -gt INTEGER2
- INTEGER1 -ge INTEGER2
- INTEGER1 -lt INTEGER2
- INTEGER1 -le INTEGER2
- \-d FILE - check if FILE exists and it is a directory
- \-e FILE - check if FILE exists

## Case
``` bash
case expression in  
    pattern_1)  
        statements  
        ;;  
    pattern_2)  
        statements  
        ;;  
    pattern_3|pattern_4|pattern_5)  
        statements  
        ;;  
    pattern-n)  
        statements  
        ;;  
    *)  
        statements  
        ;;  
esac  
```

## Loop
### For
``` bash
for variable in list  
do  
statements
done  

for (( expression1; expression2; expression3 ))  
do  
statements
done  
```

### While
``` bash
while [ expressions ];  
do  
commands
done  
```

### Until
``` bash
until [ expressions ];  
do  
commands
done  
```

## String
### Operator
- str1 = str2
- str1 != str2 
- str1 < str2 (less than)
- str1 > str2 (greater than)
- -n str (length > 0)
- -z str (length == 0)
- ${#str} (return length)

## Pattern Matching
### Wildcard
- \* - match zero or more characters
- ? - match any single character
- [...] - match any of the characters in a set
- ?(patterns) - match zero or one occurrences of the patterns
- \*(patterns) - match zero or more occurrences of the patterns
- +(patterns) - match one or more occurrences of the patterns
- @(patterns) - match one occurrence of the patterns
- !(patterns) - match anything that doesn't match one of the patterns

### Curly braces
``` bash
# cat log.txt log.csv
cat log.{txt,csv}

# cat all *.py and *.sh files
cat *{.py,.sh}

```


## Substitution
- ${foo%suffix} - remove suffix
- ${foo#prefix} - remove prefix
- ${foo%%suffix} - remove long suffix
- ${foo##prefix} - remove long prefix
- ${foo/from/to} - replace first match
- ${foo//from/to} - replace all
- ${foo/%from/to} - replace suffix
- ${foo/#from/to} - replace prefix

## Function
``` bash
# Definition
function_name () 
{  
  statements
}  

# Calling
function_name

```

### Passing Arguments
``` bash
# Calling with arguments
function_name () 
{  
  echo $1
  echo $2
  echo $3
}  

function_name arg1 arg2 arg3
```

### Variable Scope
- variables are defined as global variables by default
``` bash
local name=Joey 
```

## Array
### Initialization
``` bash
arr[0] = value_0
arr[1] = value_1
arr[2] = value_2
```

``` bash
arr=(value_0 value_1 value_2)
```

### Array Length
``` bash
${#arr[@]}
```

### Loop through the Array
``` bash
for ele in ${arr[@]}  
do  
echo $ele
done  

for i in ${!arr[@]}  
do  
echo $i ":" ${arr[$i]}
done 
```

### Adding Element
``` bash
arr+=(value)
```

### Remove Element
``` bash
unset arr[index]
```

### Delete Array
``` bash
unset arr
```

### Slice Array

``` bash
arr_slice=(${arr[@]:m:n})  
```

### Check If Files Exist
``` bash
FILE=/etc/resolv.conf
if [-f "$FILE"]; then
    echo "$FILE exists."
fi
```
- \-d FILE: True if the FILE exists and is a directory.
- \-e FILE: True if the FILE exists and is a file, regardless of type (node, directory, socket, etc.).
- \-f FILE: True if the FILE exists and is a regular file (not a directory or device).
- \-x FILE: True if the FILE exists and is executable.

### Stdio Redirection 
- \>: redirect output (default 1>)
- \<: redirect input (default 0<)
- 0: stdin
- 1: stdout
- 2: stderr
- &>: 2>&1

``` bash
# redirect the stderr to file
command 2> file

# '> file' redirect the stdout to file
# then '2>&1' redirect the stderr to stdout.
command > file 2>&1

# redirect both stdout/stderr to file
command &> file
command 2>&1 > file 
```

### Piping
redirect the stdout of the former program as the stdin of the latter program

``` bash
# count the number of particular files
ls *.txt | grep test | wc -l

# sort the content of a file
$ cat file.txt | sort | cat > sortedFile.txt

# read the specific line of a file
cat file.txt | head -3 | tail -1
```

#### xargs
execute a command using STDIN as arguments.

``` bash
# list all contents of files in the current dir
ls | xargs cat
```