joplin-notes/joplin notion extension/linux/Bash Basics.md
2026-11-04 00:33:23 +05:30

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"
```
&nbsp;
for have single quotes in literal in bash
```bash
ffmpeg -i 'The Witcher 3 In the Eternal Fire'\''s Shadow p1.mp4' -o ...
```