342 lines
No EOL
6.7 KiB
Markdown
342 lines
No EOL
6.7 KiB
Markdown
Bash Basics
|
|
https://devhints.io/bash
|
|
|
|
**Note**
|
|
- for executing commands if uses single quotes then it will pass literal text , double quotes allows commands and variables to be execured
|
|
|
|
|
|
- for loop
|
|
```bash
|
|
for arg in "$@"; do
|
|
echo "$arg"
|
|
done
|
|
|
|
for (( i=0;i<$filesCount;i++)); do
|
|
singleFile="${filesArray[$i]}"
|
|
#here I replace ALL the spaces in the file's name, by underscores.
|
|
trimmed=${singleFile// /\_}
|
|
mv "${singleFile}" "${trimmed}"
|
|
echo "renamed ${singleFile} as ${trimmed} !"
|
|
done
|
|
```
|
|
- if elif else
|
|
set of if else statements are terminated with fi
|
|
```bash
|
|
# String
|
|
if [[ -z "$string" ]]; then
|
|
echo "String is empty"
|
|
elif [[ -n "$string" ]]; then
|
|
echo "String is not empty"
|
|
else
|
|
echo "This never happens"
|
|
fi
|
|
|
|
```
|
|
- Logical operators
|
|
```bash
|
|
# Logical AND and OR
|
|
if [[ $varA == 1 && ($varB == "t1" || $varC == "t2") ]]; then
|
|
|
|
# NOT
|
|
if ! [[ $var == 2 || $var == 30 || $var == 50 ]] ; then
|
|
do something
|
|
fi
|
|
if [[ ! ($var == 2 || $var == 30 || $var == 50) ]] ; then
|
|
do something
|
|
fi
|
|
|
|
|
|
```
|
|
- Functions
|
|
```bash
|
|
myfunc() {
|
|
echo "hello $1"
|
|
}
|
|
|
|
# Same as above (alternate syntax)
|
|
function myfunc {
|
|
echo "hello $1"
|
|
}
|
|
|
|
myfunc "John"
|
|
|
|
|
|
# Returning values
|
|
myfunc() {
|
|
local myresult='some value'
|
|
echo "$myresult"
|
|
}
|
|
|
|
result=$(myfunc)
|
|
|
|
|
|
|
|
```
|
|
- Geting filename and extemsion
|
|
```bash
|
|
# First, get file name without the path:
|
|
|
|
filename=$(basename -- "$fullfile")
|
|
# or
|
|
filename="${FILEPATH##*/}"
|
|
extension_only="${filename##*.}"
|
|
filename_with_noext="${filename%.*}"
|
|
|
|
```
|
|
- array
|
|
```bash
|
|
# Declaring an array
|
|
arr=()
|
|
arr1=("hey" "there" "how")
|
|
arr2=("er" "yu")
|
|
declare -a arr3=()
|
|
|
|
# Declare associative array to be able to have keys rather than index
|
|
declare -A asscoArr
|
|
|
|
# array elements is "${arr1[@]}"
|
|
for ele in "${arr1[@]}";do
|
|
echo $ele
|
|
done
|
|
|
|
# Output
|
|
hey
|
|
there
|
|
how
|
|
|
|
# array index/keys is "${!arr1[@]}"
|
|
for i in "${!arr1[@]}";do
|
|
echo $i
|
|
done
|
|
|
|
# Accessing elements through index
|
|
"${arr1[2]}"
|
|
|
|
# getting length of array
|
|
${#arr1[@]}
|
|
|
|
```
|
|
- shift
|
|
To shift arguments to left so that first argument is lost
|
|
- C like switch case in bash
|
|
```bash
|
|
#!/bin/bash
|
|
|
|
# Loop through all the arguments
|
|
for arg in "$@"; do
|
|
case $arg in
|
|
-a|--optionA)
|
|
echo "Option A detected!"
|
|
# handle option A
|
|
;;
|
|
-b|--optionB)
|
|
echo "Option B detected!"
|
|
# handle option B
|
|
;;
|
|
*)
|
|
# Handle positional arguments or invalid flags
|
|
;;
|
|
esac
|
|
done
|
|
```
|
|
- pasing variable arguments
|
|
```bash
|
|
# Define your arguments in an array
|
|
passargs=(-x '*/node_modules/*')
|
|
|
|
# Use the array with the command
|
|
zip -r archive.zip . "${passargs[@]}"
|
|
|
|
|
|
# following method wont work
|
|
|
|
passargs="'-x */node_modules/*'"
|
|
zip -r $ARCHIVE_NAME $FILES_TO_ARCHIVE $passargs
|
|
```
|
|
- convert string which r separted by spaces to array
|
|
using declare will resolve some bugs related to delimiters
|
|
```bash
|
|
# arrow looks like following
|
|
arr1=('hey' 'there')
|
|
# if
|
|
str="hey there"
|
|
declare -a arr=($str)
|
|
# now
|
|
# arr is ('hey' 'there')
|
|
```
|
|
- extract parent directory
|
|
```bash
|
|
// Output : /home/username
|
|
echo "$PWD"
|
|
|
|
// Output : /home
|
|
echo "${dirname $PWD}"
|
|
|
|
|
|
```
|
|
### Examples
|
|
|
|
- Find non common elements from 2 array
|
|
```bash
|
|
distinctive_files(){
|
|
|
|
# dir1=$1
|
|
# dir2=$2
|
|
|
|
# arr1=( $( ls $dir1 ) )
|
|
# arr2=( $( ls $dir2 ) )
|
|
|
|
declare -a arr1=("er" "rt")
|
|
declare -a arr2=("er" "rt" "ty")
|
|
|
|
# echo "arr1: ${arr1[@]}"
|
|
# echo "arr2: ${arr2[@]}"
|
|
|
|
declare -A all_Elements
|
|
common_Files=()
|
|
distinct_Files=()
|
|
|
|
for elem in "${arr1[@]}";do
|
|
# echo "elem arr1: $elem"
|
|
((all_Elements[$elem]++))
|
|
# echo "arr1 all_Elements: ${all_Elements[$elem]}"
|
|
done
|
|
|
|
for elem in "${arr2[@]}";do
|
|
# echo "elem arr2: $elem"
|
|
((all_Elements[$elem]++))
|
|
# echo "arr2 all_Elements: ${all_Elements[$elem]}"
|
|
done
|
|
|
|
# echo "Non common elements:"
|
|
for key in "${!all_Elements[@]}" ; do
|
|
if [ ${all_Elements[$key]} -eq 1 ]; then
|
|
|
|
distinct_Files+=($key)
|
|
fi
|
|
# echo "key: $key"
|
|
done
|
|
|
|
echo "${distinct_Files[@]}"
|
|
|
|
# Calling function
|
|
disti=$(distinctive_files)
|
|
|
|
```
|
|
- Pass 2 arrays as arguments in bash
|
|
```bash
|
|
# by passing number of elements of each array
|
|
myFunc(){
|
|
local n1=$1
|
|
local n2=$2
|
|
shift 2
|
|
local arr=("$@")
|
|
arr1=()
|
|
arr2=()
|
|
i=0
|
|
for ele in "${arr[@]}"; do
|
|
echo "ele: $ele"
|
|
if [[ i -ge $n1 ]]; then
|
|
arr2+=($ele)
|
|
else
|
|
arr1+=($ele)
|
|
fi
|
|
((i++))
|
|
done
|
|
|
|
echo "arr1 ${arr1[@]}"
|
|
echo "arr2 ${arr2[@]}"
|
|
|
|
|
|
}
|
|
|
|
declare -a arr1=("er" "rt")
|
|
declare -a arr2=("er" "rt" "ty")
|
|
|
|
(added_zipped_files ${#arr1[@]} ${#arr2[@]} ${arr1[@]} ${arr2[@]})
|
|
|
|
|
|
|
|
# by passing reference(from bash 4.3 released in year 2016)
|
|
demo_multiple_arrays() {
|
|
local -n _array_one=$1
|
|
local -n _array_two=$2
|
|
printf '1: %q\n' "${_array_one[@]}"
|
|
printf '2: %q\n' "${_array_two[@]}"
|
|
}
|
|
|
|
array_one=( "one argument" "another argument" )
|
|
array_two=( "array two part one" "array two part two" )
|
|
|
|
demo_multiple_arrays array_one array_two
|
|
|
|
```
|
|
- Append certain character
|
|
```bash
|
|
#!/bin/bash
|
|
|
|
# Check if a file name is provided as an argument
|
|
if [ $# -ne 1 ]; then
|
|
echo "Usage: $0 <filename>"
|
|
exit 1
|
|
fi
|
|
|
|
# Check if the file exists
|
|
if [ ! -f "$1" ]; then
|
|
echo "File '$1' not found."
|
|
exit 1
|
|
fi
|
|
|
|
# Append semicolon to each line in the file
|
|
while IFS= read -r line; do
|
|
echo "$line;"
|
|
done < "$1" > "$1.tmp"
|
|
|
|
# Replace the original file with the modified one
|
|
mv "$1.tmp" "$1"
|
|
|
|
echo "Semicolons appended to each line in '$1'."
|
|
|
|
```
|
|
- to display ram of top processes based on ram
|
|
```sh
|
|
#!/bin/zsh
|
|
|
|
echo "Command PSS (MB)"
|
|
echo "================================================="
|
|
|
|
smem -c "command pss" |
|
|
awk '{
|
|
cmd=$1; pss=$2; uss=$3; rss=$4;
|
|
pssTotal[cmd]+=pss; ussTotal[cmd]+=uss; rssTotal[cmd]+=rss;
|
|
} END {
|
|
for (cmd in pssTotal) {
|
|
# Convert from KB to MB
|
|
pssMB = pssTotal[cmd] / 1024;
|
|
printf "%-35s %10.2f MB\n", cmd, pssMB;
|
|
}
|
|
}' | sort -k 2 -nr | head -n 10
|
|
```
|
|
- random string generation
|
|
random 16 character alphanumeric string
|
|
`tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 16; echo ''`
|
|
pure bash
|
|
```sh
|
|
# Define allowed character set
|
|
chars='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
|
|
length=16
|
|
result=''
|
|
|
|
for ((i=0; i<length; i++)); do
|
|
result+="${chars:RANDOM%${#chars}:1}"
|
|
done
|
|
|
|
echo "$result"
|
|
|
|
```
|
|
|
|
|
|
for have single quotes in literal in bash
|
|
```bash
|
|
ffmpeg -i 'The Witcher 3 In the Eternal Fire'\''s Shadow p1.mp4' -o ...
|
|
``` |