LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 08-28-2015, 10:15 PM   #1
beanaroo
LQ Newbie
 
Registered: Aug 2015
Posts: 9

Rep: Reputation: Disabled
Post Professional opinion of a bash script.


Greetings! Long time lurker, first time poster.

I recently discovered i3blocks, which provides a status line for i3bar. Each block is its own script. I attempted to write my own battery status indicator from scratch. It works!
But I'd like some seasoned advice on whether or not it's of acceptable standard and if I could be doing things 'better'. I'm still studying up on Bash Scripting and tools like awk, which I think might be better suited.

The output is three lines, which then get parsed. I'm making use of FontAwesome on my system.

PHP Code:
#!/bin/bash

# Get battery status from acpi
# $BLOCK_INSTANCE is an option that can be set in i3block.conf
BATCALL=$(acpi -grep "Battery $BLOCK_INSTANCE")

# Set Status and Percentage variables
STATUS=$(echo $BATCALL cut -d':' -f 2 cut -d',' -f 1)
PERCENT=$(echo $BATCALL cut -d',' -f 2 tr -%)

# Set Icon
if [ $STATUS == "Discharging" ] ; then
    
if [ $PERCENT -ge 90 ] ; then
        ICON
=""
    
elif $PERCENT -ge 65 ] ; then
        ICON
=""
    
elif $PERCENT -ge 40 ] ; then
        ICON
=""
    
elif $PERCENT -ge 15 ] ; then
        ICON
=""
    
elif $PERCENT -lt 15 ] ; then
        ICON
=""
    
fi
elif 
$STATUS == "Charging" ] || [ $STATUS == "Full" ] ; then
    ICON
=""
fi

echo $ICON # Full text label
echo $ICON # Short text label (Used when status line gets too long)

# Set color value for the above
if [ $PERCENT -ge 85 ] ; then
    
echo "#9FA91F"
elif $PERCENT  -ge 50 ] ; then
    
echo "#FFBF00"
elif $PERCENT  -ge 20 ] ; then
    
echo "#FF7E00"
elif $PERCENT  -lt 20 ] ; then
    
echo "#FF033E"
fi 
Thanks for reading!
 
Old 08-28-2015, 10:40 PM   #2
goumba
Senior Member
 
Registered: Dec 2009
Location: New Jersey, USA
Distribution: Fedora, OpenSUSE, FreeBSD, OpenBSD, macOS (hack). Past: Debian, Arch, RedHat (pre-RHEL).
Posts: 1,335
Blog Entries: 7

Rep: Reputation: 402Reputation: 402Reputation: 402Reputation: 402Reputation: 402
Looks good, but I am no pro.

Very nice on using $() as opposed to backticks.

Code:
echo $ICON # Full text label
echo $ICON # Short text label (Used when status line gets too long)
The same thing, did you mean to do something else with that?

Comparing strings, typically the variable name will be in quotes as well, so you'll see things like this elsewhere:

Code:
if [ "$STATUS" == "Discharging" ]; then
One other thing is that usually uppercase names are used with environment variables, lower case variable names are preferred by many in shell scripts.
 
Old 08-29-2015, 12:18 AM   #3
beanaroo
LQ Newbie
 
Registered: Aug 2015
Posts: 9

Original Poster
Rep: Reputation: Disabled
Thanks, goumba! I've updated the string comparisons and variable cases.

The short text version is used by the status bar when there isn't enough space for the full text version. In my case they are both only one character long.
 
Old 08-29-2015, 04:54 AM   #4
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
Very nice

[[ ... ]] has advantages over [ ... ] as explained at http://mywiki.wooledge.org/BashFAQ/031

There is a convention you may like of using lower-case names for your own variables. The advantage is that any upper case names stand out as being either bash internal variables or environment variables.

Numeric tests -- ((...)) -- can be used instead of [[ ... ]] with numeric comparison operators. They have the advantages of being more concise, of being immediately recognisable as numeric tests and of supporting the $ dereference operator to yield their numeric value.
 
1 members found this post helpful.
Old 08-29-2015, 05:08 AM   #5
unSpawn
Moderator
 
Registered: May 2001
Posts: 29,415
Blog Entries: 55

Rep: Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600
Quote:
Originally Posted by goumba View Post
lower case variable names are preferred by many in shell scripts.
That indeed is personal preference because likewise one could say upper case var names make them stand out making things easier to read.


Quote:
Originally Posted by beanaroo View Post
(..) and if I could be doing things 'better'.
Looks good. Here's my take on things using an array and including error handling:
Code:
#!/bin/bash --
# Uncomment next for debugging:
# set -vx
# Uncomment next for renicing:
# which renice >/dev/null 2>&1 && renice -n +20 -p $$
# which ionice >/dev/null 2>&1 && ionice -c 3 -p $$
# Uncomment next if shouldn't be run as root:
# [ $(id -u 2>/dev/null) -eq 0 ] && { echo "Unpriv only, exiting."; exit 1; }
# Uncomment next if shouldn't run if no Xorg in sight:
# [ -z ${DISPLAY} ] && { echo "Couldnt find Xorg display, exiting."; exit 1; }
# Missing environment variable:
[ -z ${BLOCK_INSTANCE} ] && { echo "Couldnt find envvar, exiting."; exit 1; }
# Missing binaries:
BINARIES="acpi"; for ITEM in $BINARIES; do which "${ITEM}" >/dev/null 2>&1 \
|| { echo "Please install acpi first, exiting."; exit 1; }; done

# Initialization done, now get battery status from acpi into array:
# $BLOCK_INSTANCE is an arbitrary string env var set in i3block.conf
BATCALL=($(acpi -b 2>/dev/null| grep "Battery ${BLOCK_INSTANCE}"))
# Mandatory amount of items in array:
[ ${#BATCALL[@]} -ne 3 ] || { echo "acpi returns wonky values, exiting."; exit 1; }
# Set Status and Percentage variables
STATUS=${BATCALL[2]}; STATUS=${STATUS//,/}
[ -z ${STATUS} ] && { echo "Empty var, exiting."; exit 1; }
PERCENT=${BATCALL[3]}; PERCENT=${PERCENT//%/}
[ -z ${PERCENT} ] && { echo "Empty var, exiting."; exit 1; }
[ ${PERCENT} -eq ${PERCENT} ] || { echo "Odd int value, exiting."; exit 1; }

# Set Icon
case "${STATUS}" in 
Dischar*)
     if [ $PERCENT -ge 90 ]; then ICON=""
      elif [ $PERCENT -ge 65 ]; then ICON=""
      elif [ $PERCENT -ge 40 ]; then ICON=""
      elif [ $PERCENT -ge 15 ]; then ICON=""
      elif [ $PERCENT -lt 15 ]; then ICON=""
     fi
    ;;
Charg*|Full) ICON=""
    ;;
*) ICON=""
    ;;
esac

echo $ICON # Full text label
echo $ICON # Short text label (Used when status line gets too long)

# Set color value for the above
if [ $PERCENT -ge 85 ] ; then echo "#9FA91F"
elif [ $PERCENT  -ge 50 ] ; then echo "#FFBF00"
elif [ $PERCENT  -ge 20 ] ; then echo "#FF7E00"
elif [ $PERCENT  -lt 20 ] ; then echo "#FF033E"
fi

exit 0
 
Old 08-30-2015, 01:40 AM   #6
beanaroo
LQ Newbie
 
Registered: Aug 2015
Posts: 9

Original Poster
Rep: Reputation: Disabled
Smile

@catkin - I noticed the double brackets in a script for WiFi status but couldn't find a quick answer to the difference. Thanks for the link! The entire FAQ looks awesome!

@unSpawn - I just started learning case statements today. Thank you. I like the style much better. There's a lot of useful stuff in there too!
 
Old 08-30-2015, 07:47 AM   #7
Keith Hedger
Senior Member
 
Registered: Jun 2010
Location: Wiltshire, UK
Distribution: Void, Linux From Scratch, Slackware64
Posts: 3,150

Rep: Reputation: 856Reputation: 856Reputation: 856Reputation: 856Reputation: 856Reputation: 856Reputation: 856
When using string comaparisons its a good idea to add an extra character to both string to prevent null string errors so
Code:
if [ "X$var1" = "X$var2" ];then
...
fi
The two 'X's cancel and it prevents an error if one variable is not set.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] Bash Script - Reading User Input while Processing output from Command within Bash cleeky Linux - General 5 05-27-2014 02:57 PM
Opinion on Slackbuild script for Echinus window manager. Mol_Bolom Slackware 5 03-23-2011 11:06 AM
[Bash] Denied Script * Opinion's Welcome * zer0signal Programming 10 02-01-2011 12:57 AM
SSH connection from BASH script stops further BASH script commands tardis1 Linux - Newbie 3 12-06-2010 08:56 AM
[SOLVED] Using a long Bash command including single quotes and pipes in a Bash script antcore Linux - General 9 07-22-2009 11:10 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 03:09 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration