Bash (script)
- Introduction
TODO
2. Quick reference
2.1. Find files by name, recursive
find . -name "*.java"
2.2. Find files containing given text, recursive
grep -rnw '/path/to/somewhere/' -e 'pattern'
-r or -R is recursive,
-n is line number, and
-w stands for match the whole word.
-l (lower-case L) can be added to just give the file name of matching files.
-e is the pattern used during the search
Along with these, --exclude, --include, --exclude-dir flags could be used for efficient searching:
This will only search through those files which have .c or .h extensions:
grep --include=\*.{c,h} -rnw '/path/to/somewhere/' -e "pattern"
This will exclude searching all the files ending with .o extension:
grep --exclude=\*.o -rnw '/path/to/somewhere/' -e "pattern"
For directories it's possible to exclude one or more directories using the --exclude-dir parameter. For example, this will exclude the dirs dir1/, dir2/ and all of them matching *.dst/:
grep --exclude-dir={dir1,dir2,*.dst} -rnw '/path/to/somewhere/' -e "pattern"
3. Bash editors
3.1. Plugin for vim
bash-support.vim : Bash IDE -- Insert code snippets, run, check and debug the code and look up help
https://www.vim.org/scripts/script.php?script_id=365
Make Vim as Your Bash-IDE Using bash-support Plugin
https://www.thegeekstuff.com/2009/02/make-vim-as-your-bash-ide-using-bash-support-plugin
Note: Verified on Ubuntu 20.04.1 LTS w/ vim installed [sudo apt install vim]
4. Examples
4.1. Maven execution depending on script arguments
#!/bin/bash
export APIGTW_USER=aws_user
if [ $# -eq 2 ] && [ 'run' = $1 ] && [ 'main' = $2 ]; then
# ::Run the Spring Boot app using a PostgreSQL database
./mvnw spring-boot:run -DskipITs
elif [ $# -eq 2 ] && [ 'run' = $1 ] && [ 'test' = $2 ]; then
# ::Run the Spring Boot app using a H2 in-memory database (intended for developers only)
./mvnw spring-boot:run -DskipITs -Dspring-boot.run.arguments=--spring.config.location=file:./src/test/resources/
elif [ $# -eq 1 ] && [ 'test' = $1 ]; then
# ::Run unit tests and jacoco checks/report (intended for developers only)
./mvnw verify -DskipITs
else
echo "**** ERROR: Arguments not recognized ****"
fi
4.2. cURL & response JSON parsing using Python, w/ exit codes
It uses cURL for retrieving info about countries (exit code 27 if it fails).
It user python for getting the name of the 1st currency of an specific country (exit code 28 if it fails).
It prints the value (exit code 0 if it success)
#!/usr/bin/bash
# #################################
# It requires Python 3 installed
# $ sudo apt update
# $ sudo apt install python3
# #################################
###################################################
# Get json value specified by key
# Globals: None
# Arguments: 2
# ${1} - json string
# ${2} - json key, eg: "[178]['currencies'][0]['name']"
# Input: file | here string | pipe
# get_json_value "Arguments" < file
# get_json_value "Arguments <<< "${variable}"
# echo something | get_json_value "Arguments"
# Result: print extracted value
# Exit codes: 1 for error
###################################################
get_json_value() {
json_str=$1
json_key=$2
echo -n $json_str | python3 -c "import json, sys; print(json.load(sys.stdin)$json_key)"
}
countries_json=$(curl -fLsS -H "Accept: application/json" "https://restcountries.eu/rest/v2/all")
if [ $? -ne 0 ]; then
exit 27
fi
country4_json=$(get_json_value "$countries_json" "[178]['currencies'][0]['name']")
if [ $? -ne 0 ]; then
exit 28
fi
echo $country4_json
#Sample output: Polish złoty
exit 0
Sample executions:
a) Success
$ ./sample2.sh
Polish złoty
$ echo $?
0
b) Invalid REST hostname
$ ./sample2.sh
curl: (6) Could not resolve host: restcountries.invalid
$ echo $?
27
c) Not found REST response
$ ./sample2.sh
curl: (22) The requested URL returned error: 404
$ echo $?
27
d) Invalid json key
$ ./sample2.sh
Traceback (most recent call last):
File "<string>", line 1, in <module>
KeyError: 'invalid'
$ echo $?
28
4.3. Function returning strings and exit codes
Notes: Exit codes range [0..255] and an 'exit' inside a function quits the function but not the main script.
1st option: Using global variables
#!/bin/bash
ret_global_test()
{
global="Leaving response in a global var"
}
global=""
ret_global_test
echo $global
Previous script outputs: "Leaving response in a global var"
2nd option: Using command substitution
#!/bin/bash
exit_test()
{
echo "Yes, that's me"
exit 27
}
exit_test
Previous script outputs: "Yes, that's me"
3rd option: Using in/out parameter
#!/bin/bash
my_function() {
[ $1 ] || { echo "Wrong usage"; exit 1; }
myvar="Let us return something"
eval $1='$myvar'
}
my_function param_in_out
echo $param_in_out
The previous script outputs:
Let us return something
If we forget to pass the in/out parameter we would get:
Wrong usage