⬅️ **[[$-Tools|Tools]]**
***
# Bash
- [YourOwnLinux - Bash Array](http://www.yourownlinux.com/2016/12/bash-scripting-arrays-examples.html)
## [[zsh]]
## Starting a script
- **Issue: `Syntax error: "(" unexpected` when creating an array:** When you use `./scriptname.sh` it executes with `/bin/bash` as in the first line with `#!`. But when you use sh scriptname.sh it executes sh, not bash.
```bash
#!/usr/bin/env bash
# Use set -o errexit (a.k.a. set -e) to make your script exit when a command fails.
set -o errexit
# Use set -o nounset (a.k.a. set -u) to exit when your script tries to use undeclared variables.
set -o nounset
# Use set -o xtrace (a.k.a set -x) to trace what gets executed. Useful for debugging.
# set -o xtrace
# Use set -o pipefail in scripts to catch mysqldump fails in e.g. mysqldump |gzip. The exit status of the last command that threw a non-zero exit code is returned.
set -o pipefail
```
### Run a shell script as a different user
`/bin/su -c "/path/to/backup_db.sh /tmp/test" - postgres`
### Run Oracle SQL script and exit from sqlplus.exe via command prompt
`echo exit | sqlplus user/pass@connect @scriptname`
## Handling exit codes
- [Bash get exit code of command on a Linux / Unix](https://www.cyberciti.biz/faq/bash-get-exit-code-of-command/)
- Output exit code of last command: `echo $?`
## Array
```bash
### Array anlegen
myArray=("cat" "dog" "mouse" "frog)
### loop through it:
for i in ${!myArray[@]}; do
echo "element $i is ${myArray[$i]}"
done
### Output:
element 0 is cat
element 1 is dog
element 2 is mouse
element 3 is frog
```
## File handling
### Copy latest file of folder
Source: https://unix.stackexchange.com/questions/195304/how-do-i-copy-the-latest-file-from-one-directory-to-another
Here, `ls -d` gives the absolute path.
In your command, as `ls` is not returning absolute paths, you must run that from the source directory to get the file copied. As you have run it from some other directory that does not have the file, the error `No such file or directory` being shown.
Also as you have spaces in the path we need to quote `ls -dtr1 /Users/Me/Documents/Coffi\ Work/FTP\ Backup\ Shell\ Script/Original/* | tail -1` so that shell does not do word splitting on the output of it.
```bash
cp -p "`ls -dtr1 "$SRC_DIR"/* | tail -1`" "$DEST_DIR"
```
### Remain original file timestamps
If you want to preserve the original timestamps, use
```bash
touch -r <original_file> <new_file>
```
This copies the timestamps from another file.
### Read file line by line
```sh
while IFS= read -r line; do
printf '%s\n' "$line"
done < input_file
```
## Variables
- Set a new variable: `PARAM_APP1="app1"`
- Get value from Linux Command: `isHddThere=$(sudo blkid | grep '1a7cdbbc-af98-4eb7-b195-e84fa1f87460')`
## Functions and Scripts
- [Ryans Tutorials - Functions](https://ryanstutorials.net/bash-scripting-tutorial/bash-functions.php)
### Create Scripts during execution
```bash
testVar="Variable for the dynamically created file"
cat <<EOT >/path/to/file.md
# Test Header
- Text1
- Text2
- Here is the content of the testVar = "${testVar}"
- This content is then created during execution.
EOT
```
## User interaction
### Input from user
`read <variable_name`
### Select Menu
The select construct generates a menu from a list of items. It has almost the same syntax as the for loop:
```bash
select ITEM in [LIST]
do
[COMMANDS]
done
```
The [LIST] can be a series of strings separated by spaces, a range of numbers, output of a command, an array, and so on. A custom prompt for the select construct can be set using the PS3 environment variable.
When the select construct is invoked, each item from the list is printed on the screen (standard error), preceded with a number.
### Scripts expecting User input
Here is the call of a script on the CLI with EOF containing the 5 User inputs per line:
```bash
sh script_name.sh <<EOF
Input1
Input2
Input 4
EOF
```
## Controls
### If..else
**Default example:**
```bash
singleInput=""
# read user input
read singleInput
if [ "$singleInput" = "" ]
then
singleInput="null"
else
summary="$summary \n- $singleInput"
fi
```
**Some OR-Conditions:**
```bash
if [ $1 == ${PARAM_APP1} -o $1 == ${PARAM_APPN} -o $1 == ${PARAM_DB} ]; then
(...)
fi
```
**Check if file / folder exists:**
```bash
if [ -f /apps/SD/Last_Delivery.tar ]; then
echo "|-- Delete old /apps/SD/Last_Delivery.tar"
rm -f /apps/SD/Last_Delivery.tar
fi
echo "|--- Create temporary folder ${DELIVERY_BASE_RTDIR_TEMP}"
if [ ! -d ${DELIVERY_BASE_RTDIR_TEMP} ]; then
mkdir -p ${DELIVERY_BASE_RTDIR_TEMP}
fi
```
### Switch..Case
```bash
read category
fileName=""
case "$category" in
1) fileName="Privat"
;;
2) fileName="Natur"
;;
3) fileName="Finanzen"
;;
4) fileName="Arbeit"
;;
5) fileName="Bib"
;;
*) echo "Falsche eingabe"
exit 1
;;
esac
```
## Loops
### While Loop
```bash
summary=""
singleInput=""
while [ "$singleInput" != "null" ]
do
read singleInput
if [ "$singleInput" = "" ]
then
singleInput="null"
else
summary="$summary \n- $singleInput"
fi
done;
```
## Text and Formats
### Concat text in string
`output="\n### $(date +'%F') $title $articleLine $summary"`
### Formatted `echo` output without `\n` etc.
`echo -e $output`
### Output into a file
- Concat to existing file ` >> `
- `echo -e $output >> $filePath/$fileName-$(date +'%Y-%m')-news.md`
- Overwrite existing file ` > `
### Format date
- `$(date +'%A %F %T %Z')` is `Friday 2020-01-24 21:57:19 CET`
- `$(date +'%F')` is `2020-01-24`
- `$(date +'%u')` is `1` for Monday, etc.
#
***
Related:
- [[$-Software|Software]]
- [[$-Linux|Linux]]