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
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
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.
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...
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
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"