Replace if with for in progress bar - bash

I have an if-testing construct for a bash-progress bar:
progress_bar () {
PROGRESS=`expr $( cat $CONTROL_FILE ) - 100 | tr "-" "\r"`
clear
if [ "$PROGRESS" -eq 10 ]
then
echo -n "$PROGRESS % [# ] "
fi
if [ $PROGRESS -eq 20 ]
then
echo -n "$PROGRESS % [## ] "
fi
if [ $PROGRESS -eq 30 ]
then
echo -n "$PROGRESS % [### ] "
fi
if [ $PROGRESS -eq 40 ]
then
echo -n "$PROGRESS % [#### ] "
fi
if [ $PROGRESS -eq 50 ]
then
echo -n "$PROGRESS % [##### ] "
fi
if [ $PROGRESS -eq 60 ]
then
echo -n "$PROGRESS % [###### ] "
fi
if [ $PROGRESS -eq 70 ]
then
echo -n "$PROGRESS % [####### ] "
fi
if [ $PROGRESS -eq 80 ]
then
echo -n "$PROGRESS % [######## ] "
fi
if [ $PROGRESS -eq 90 ]
then
echo -n "$PROGRESS % [######### ] "
fi
if [ $PROGRESS -eq 100 ]
then
echo "$PROGRESS % [##########]"
fi}
It works well: A "#" will be added each time when +10 are counted. My question is: Is there a way to make this look more beautiful? Like a for-loop or something else?
Thanks

I'd do it like this:
progress_bar () {
local percent hashes
hashes='##########'
percent=$(<"$CONTROL_FILE")
printf '\r%d %% [%-10s] ' $((100 - percent)) "${hashes:percent/10}"
}

Would you please try the following:
progress_bar() {
local progress n bar
progress=$(expr $(<"$CONTROL_FILE") - 100 | tr "-" "\r")
clear
n=$(( $progress / 10 ))
if (( $progress > 0 )); then
bar=$(printf "%${n}s" " " | tr " " "#")
fi
printf "%s %% [%s]" "$progress" "$bar"
(( $progress >= 100 )) && echo # put newline when done
}
printf "%${n}s" " " | tr " " "#" repeats a whitespace $n times, then
relace them with #s of the same count.
As it is not recommended to use uppercases for user's variables, I've
changed PROGRESS to progress.

Related

I'm using this shell script to identify the maximum and minimum of the performed arithmetic operation but facing issue with float value in if block

read -p "enter first number : " a
read -p "enter second number : " b
read -p "enter third number : " c
if [ $b -gt 0 ]
then
w=`echo $a $b $c | awk '{print $1+$2*$3}'`;
echo $w;
x=`echo $a $b $c | awk '{print $1%$2+$3}'`
echo $x
y=`echo $c $a $b | awk '{print $1+$2/$3}'`
echo $y
z=`echo $a $b $c | awk '{print $1*$2+$3}'`
echo $z
if [ $w -gt $x ] && [ "($w -gt $y | bc)" ] && [ $w -gt $z ]
then
echo $w"w"
elif [ $x -gt $w ] && [ "( $x -gt $y | bc )" ] && [ $x -gt $z ]
then
echo $x"x"
elif [ $z -gt $w ] && [ $z -gt $x ] && [ "($z -gt $y | bc)" ]
then
echo $z"z"
else
echo $y"y"
fi
if [ $w -lt $x ] && [ "( $w -lt $y | bc )" ] && [ $w -lt $z ]
then
echo $w"w"
elif [ $x -lt $w ] && [ "( $x -lt $y | bc )" ] && [ $x -lt $z ]
then
echo $x"x"
elif [ $z -lt $w ] && [ $z -lt $x ] && [ "($z -lt $y | bc )" ]
then
echo $y"y"
else
echo $z"z"
fi
fi

How do I make this bitwise code more concise?

My bitwise code which works is:
#!/bin/bash -e
random=$((RANDOM % 32));
bitWiseAnd() {
local IFS='&'
printf "%s\n" "$(( $* ))"
}
echo "random=${random}";
if [ $(bitWiseAnd ${random} "0x10") -ne 0 ]; then
echo "1"
else
echo "0"
fi
if [ $(bitWiseAnd ${random} "0x8") -ne 0 ]; then
echo "1"
else
echo "0"
fi
if [ $(bitWiseAnd ${random} "0x4") -ne 0 ]; then
echo "1"
else
echo "0"
fi
if [ $(bitWiseAnd ${random} "0x2") -ne 0 ]; then
echo "1"
else
echo "0"
fi
if [ $(bitWiseAnd ${random} "0x1") -ne 0 ]; then
echo "1"
else
echo "0"
fi
A sample output from the above code:
random=15
0
1
1
1
1
I have no idea how this code works. Can this code be made more concise?
You could use a for loop instead of repeated if blocks. Also, the for loop spells out your purpose more clearly, like this:
#!/bin/bash -e
bitWiseAnd() {
local IFS='&'
printf "%s\n" "$(( $* ))"
}
random=$((RANDOM % 32));
echo "random=${random}";
for i in 10 8 4 2 1; do
if [ $(bitWiseAnd ${random} "0x$i") -ne 0 ]; then
echo "1"
else
echo "0"
fi
done
Output:
random=10
0
1
0
1
0
Also, the function below
bitWiseAnd() {
local IFS='&'
printf "%s\n" "$(( $* ))"
}
could be made more explicit this way, as long as we are looking at just two input arguments:
bitWiseAnd() {
printf "%s\n" $(($1 & $2))
}
This won't produce the exact same output as you need, because you asked for an optimization and it doesn't involve multiple useless echo statements.
Another approach would be using a while-loop and check if bit-positions are still valid. I have removed the useless echo statements, assuming you don't need any of that and just want to improve the code.
bitMask="0x10"
while [ $(bitWiseAnd "31" "$bitMask") -ne 0 ] && ((bitMask))
do
bitMask=$((bitMask >> 1))
done
Just replace the hard-coded number 31 with the variable value $random and bitMask of your choice.

Using shell script which checks if the user has logged in twice into Unix server and displays the details of the users

Here I want to display logname of my system, if I logged in twice.
But displays many other lognames also.
v1=`who | wc -l`
c=`expr $v1 - 1`;
count=0
declare -a val
val=`who | cut -d" " -f1`
echo "$c"
temp=0
while [ $temp -le $c ]
do
if [ "{$val[$v]}" -eq `logname` ]
then
count=`expr $count + 1`
if [ $count -eq 2 ]
then
echo "`logname`, `uname`, `hostname`"
else
echo "No one";
fi
temp=`expr $temp + 1`
echo $temp
fi
done
Kindly check my code...

Inner If else statement in Shell Script

While i am executing following code, when if [ $c_count -eq $p_count ] get fails then control goes directly to outer else part. But it should go to inner else part.
What is issue in this...?
while [ "${arr2[$j]}" != "P" ]
do
if [ $j -ge $i ]
then
break
fi
if [ "${arr1[$j]}" == "M" -a $p_count -ne 0 ]
then
c_count=`grep -c "<${arr3[$j]}>" $2`
if [ $c_count -eq $p_count ]
then
echo "${arr1[$j]} ${arr2[$j]} Y $c_count ${arr3[$j]} >>>>>"
else
echo "${arr1[$j]} ${arr2[$j]} N $c_count ${arr3[$j]} "
mcinvalid=`expr $mcinvalid + 1`
echo "Count Incremented"
fi
else
c_count=`grep -c "<${arr3[$j]}>" $2`
echo "${arr1[$j]} ${arr2[$j]} N $c_count ${arr3[$j]} -------"
fi
j=`expr $j + 1`
done

BASH function: syntax error near unexpected token `'2''

I am completely lost as to why this error keeps happening, I am fairly certain that I am using the correct syntax, however, every time I execute this BASH script, I get the following error:
/home/clucky/MCServerBackup/MCServerBackup.sh: line 200: syntax error near unexpected token `'2''
/home/clucky/MCServerBackup/MCServerBackup.sh: line 200: ` logInfo() '2' "none" "Minecraft: $minecraftsize.$minecraftsized $minecraftunit"'
The line in particular that it appears to be refrencing is line 200, which is where the code attempts to execute the function logInfo() as follows:
logInfo() '2' "none" "Minecraft: $minecraftsize.$minecraftsized $minecraftunit"
In the above line of code, 2 is the indent level (2 x 5 spaces). none tells the function to ignore the logLevel that is specified in the configuration and log it anyway. Minecraft: $minecraftsize...$minecraftunit is what is being added into the log file, which the words preceeded by a $ are of course variables. The entire code can be viewed below.
#! /usr/bin/env bash
#Declare Functions
logInfo() {
if [ "$logInFile" == "true" ] || [ "$logInConsole" == "true" ] ; then
let tabAmount=5*$1
indent=""
for (( indentrepeat=0; indentrepeat < $tabAmount; indentrepeat++ ))
do
indent="$indent "
done
if [ "$2" == "none" ] ; then
infoItem="$3"
else
if [ "$logLevel" == "high" ] ; then
if [ "$2" == "subtask" ] ; then
#High + Subtask
infoItem="`date '+%H:%M:%S'` $3"
elif [ "$2" == "task" ] ; then
#High + Task
infoItem="`date '+%H:%M:%S'` $3"
fi
elif [ "$logLevel" == "medium" ] ; then
if [ "$2" == "subtask" ] ; then
#Medium + Subtask
infoItem="$3"
elif [ "$2" == "task" ] ; then
#Medium + Task
infoItem="`date '+%H:%M:%S'` $3"
fi
else
if [ "$2" == "subtask" ] ; then
#Low + Subtask
infoItem=''
elif [ "$2" == "task" ] ; then
#Low + Task
infoItem="$3"
fi
fi
fi
if [ "$logInFile" == "true" ] ; then
echo -e "$indent$infoItem" >> backup.log
fi
if [ "$logInConsole" == "true" ] ; then
echo -e "$indent$infoItem"
fi
fi
}
logError() {
if [ "$logInFile" == "true" ] || [ "$logInConsole" == "true" ] ; then
let tabAmount=5*$1
indent=""
for (( indentrepeat=0; indentrepeat < $tabAmount; indentrepeat++ ))
do
indent="$indent "
done
if [ "$logInFile" == "true" ] && [ "$logErrors" == "true" ] ; then
echo -e "$indent[ERROR] $2" >> backup.log
fi
if [ "$logInConsole" == "true" ] && [ "$logErrors" == "true" ] ; then
echo -e "$indent[ERROR] $2"
fi
fi
}
#Set Variables
source config.sh
minecraftsize=0
sqlsize=0
websitesize=0
timedate=`date '+%m.%d.%Y-%H:%M'`
#Update
if [ $version != "1.0.0" ] ; then
source update.sh
fi
#Trigger General Settings
echo -ne "\033]0;$serverName - Backup\007"
if [ "$serverDirectory" == "default" ] ; then
BINDIR="$(dirname "$(readlink -fn "$0")")"
cd "$BINDIR"
else
if [ -d "$serverDirectory" ] ; then
cd "$serverDirectory"
else
directoryExists=false
echo '$serverDirectory defined as '"$serverDirectory"' does not exist. Please double check your configuration and make sure this folder exists.'
if [ "$logInFile" == "true" ] ; then
echo "-------------- `date '+%d-%B-%Y %H:%M'` --------------" >> backup.log
echo -e ' [ERROR] $serverDirectory defined as '"$serverDirectory"', does not exist. Please double check your configuration and make sure this folder exists.'"\n" >> backup.log
fi
fi
fi
if [ "$purgeFiles" == "true" ] || [ "$backupMinecraft" == "true" ] || [ "$backupMySQL" == "true" ] || [ "$backupWebsite" == "true" ] && [ "$directoryExists" != "false" ] ; then
echo "-------------- `date '+%d-%B-%Y %H:%M'` --------------" >> backup.log
#Create Directories
echo "[`date '+%H:%M:%S'`] Directory Creation Started" >> backup.log
if [ ! -d ".backups" ] ; then
mkdir -p .backups
fi
mkdir -p .backups/$timedate
if [ "$backupMySQL" == "true" ] ; then
mkdir -p .backups/$timedate/MySQL
fi
if [ "$backupWebsite" == "true" ] ; then
mkdir -p .backups/$timedate/Website
fi
if [ "$backupMinecraft" == "true" ] ; then
mkdir -p .backups/$timedate/MinecraftServers
fi
echo "[`date '+%H:%M:%S'`] Directory Creation Completed" >> backup.log
#Backup Minecraft Servers
if [ "$backupMinecraft" == "true" ] ; then
echo "[`date '+%H:%M:%S'`] Minecraft Backup Started" >> backup.log
for (( servercount = 0; servercount < ${#mcservers[#]}; servercount++ ))
do
echo " ${mcservers[servercount]}" >> backup.log
tar -zcpf .backups/$timedate/MinecraftServers/${mcservers[servercount]}.tar.gz --directory ${mcservers[servercount]} ${fileexcludes[servercount]} .
minecraftsize=`expr $minecraftsize + $(ls -la .backups/$timedate/MinecraftServers/${mcservers[servercount]}.tar.gz | awk '{ print $5}')`
done
echo "[`date '+%H:%M:%S'`] Minecraft Backup Completed" >> backup.log
fi
#Copy MySQL Databases
if [ "$backupMySQL" == "true" ] ; then
echo "[`date '+%H:%M:%S'`] MySQL Backup Started" >> backup.log
for (( sqlcount = 0; sqlcount < ${#sqldatabases[#]}; sqlcount++ ))
do
if [[ "${sqldatabases[sqlcount]}" =~ # ]] ; then
sqldatabases[sqlcount]=${sqldatabases[sqlcount]//[#]/}
mysqldump -u"$sqluser" -p"$sqlpass" -h"$sqlhost" ${sqldatabases[sqlcount]} > .backups/$timedate/MySQL/${sqldatabases[sqlcount]}.sql;
sqlsize=`expr $sqlsize + $(ls -la .backups/$timedate/MySQL/${sqldatabases[sqlcount]}.sql | awk '{ print $5}')`
echo " ${sqldatabases[sqlcount]}*" >> backup.log
else
mysqldump -u"$sqluser" -p"$sqlpass" -h"$sqlhost" --skip-lock-tables ${sqldatabases[sqlcount]} > .backups/$timedate/MySQL/${sqldatabases[sqlcount]}.sql;
sqlsize=`expr $sqlsize + $(ls -la .backups/$timedate/MySQL/${sqldatabases[sqlcount]}.sql | awk '{ print $5}')`
echo " ${sqldatabases[sqlcount]}" >> backup.log;
fi
done
fi
#Backup Website
if [ "$backupWebsite" == "true" ] ; then
echo "[`date '+%H:%M:%S'`] Website Backup Started" >> backup.log
if [ "$websiteDirectory" == "default" ] ; then
websiteDirectory=var/www/
fi
if [ -d "$websiteDirectory" ] ; then
tar -zcpf .backups/$timedate/Website/website.tar.gz --directory $websiteDirectory $websiteExcludes .
echo "[`date '+%H:%M:%S'`] Website Backup Completed" >> backup.log
else
logError "5" "\0044websiteDirectory defined as $websiteDirectory does not exist. Please double check your configuration and make sure this folder exists."
echo "[`date '+%H:%M:%S'`] Website Backup Cancelled" >> backup.log
fi
fi
#Purge files 3 days old
if [ "$purgeFiles" == "true" ] ; then
echo "[`date '+%H:%M:%S'`] Purging Old Backups" >> backup.log
find .backups* -mmin +$purgeTime -exec rm --recursive {} \;
echo "[`date '+%H:%M:%S'`] Purging Complete" >> backup.log
fi
#Read back file size
let filesize=$minecraftsize+$sqlsize+$websitesize
if [ "$filesize" -ge 1024 ] ; then
if [ "$filesize" -ge 1048576 ] ; then
if [ "$filesize" -ge 1073741824 ] ; then
filedivider=1073741824
fileunit="GB"
else
filedivider=1048576
fileunit="MB"
fi
else
filedivider=1024
fileunit="KB"
fi
else
filedivider=1
fileunit="Bytes"
fi
let filesized='(''('$filesize%$filedivider')'*100')'/$filedivider
let filesize=$filesize/$filedivider
echo " Total Compression Size: $filesize.$filesized $fileunit" >> backup.log
if [ "$backupMinecraft" == "true" ] ; then
if [ "$minecraftsize" -ge 1024 ] ; then
if [ "$minecraftsize" -ge 1048576 ] ; then
if [ "$minecraftsize" -ge 1073741824 ] ; then
minecraftdivider=1073741824
minecraftunit="GB"
else
minecraftdivider=1048576
minecraftunit="MB"
fi
else
minecraftdivider=1024
minecraftunit="KB"
fi
else
minecraftdivider=1
minecraftunit="Bytes"
fi
let minecraftsized='(''('$minecraftsize%$minecraftdivider')'*100')'/$minecraftdivider
let minecraftsize=$minecraftsize/$minecraftdivider
logInfo() '2' "none" "Minecraft: $minecraftsize.$minecraftsized $minecraftunit"
fi
if [ "$backupMySQL" == "true" ] ; then
if [ "$sqlsize" -ge 1024 ] ; then
if [ "$sqlsize" -ge 1048576 ] ; then
if [ "$sqlsize" -ge 1073741824 ] ; then
sqldivider=1073741824
sqlunit="GB"
else
sqldivider=1048576
sqlunit="MB"
fi
else
sqldivider=1024
sqlunit="KB"
fi
else
sqldivider=1
sqlunit="Bytes"
fi
let sqlsized='(''('$sqlsize%$sqldivider')'*100')'/$sqldivider
let sqlsize=$sqlsize/$sqldivider
echo " MySQL: $sqlsize.$sqlsized $sqlunit" >> backup.log
fi
if [ "$backupWebsite" == "true" ] ; then
if [ "$websitesize" -ge 1024 ] ; then
if [ "$websitesize" -ge 1048576 ] ; then
if [ "$websitesize" -ge 1073741824 ] ; then
websitedivider=1073741824
websiteunit="GB"
else
websitedivider=1048576
websiteunit="MB"
fi
else
websitedivider=1024
websiteunit="KB"
fi
else
websitedivider=1
websiteunit="Bytes"
fi
let websitesized='(''('$websitesize%$websitedivider')'*100')'/$websitedivider
let websitesize=$websitesize/$websitedivider
echo " Website: $websitesize.$websitesized" >> backup.log
fi
echo "" >> backup.log
fi
As I stated earlier, I am completely lost, so any assistance would be greatly appreciated. Thank you!
You don't invoke a function with parentheses. Change:
logInfo() '2' "none" "Minecraft: $minecraftsize.$minecraftsized $minecraftunit"
to
logInfo '2' "none" "Minecraft: $minecraftsize.$minecraftsized $minecraftunit"

Resources