I've revised my Bash script for a DWM status bar based on earlier feedback. It updates volume every 0.2 seconds, refreshes the time, CPU usage, and memory usage every 10 seconds, and checks whether DWM is still running every 5 seconds before exiting. The script currently uses pactl, awk, grep, head, date, pgrep, and xsetroot. I'd appreciate more suggestions for improving its efficiency, simplifying the parsing, or making the CPU and memory readings more accurate. In particular, I'm wondering whether I should avoid piping pactl output, combine the two memory calculations, and improve the CPU usage measurement.
4 Answers
The script is a nice start, but the volume parsing can be simplified. Since you only need the first match, use grep with a maximum count instead of piping into head: pactl get-sink-volume @ | grep -m 1 -Po '[0-9]+(?=%)'. You can also use Bash arithmetic directly, such as (( count % 25 == 0 )), rather than nesting [ ] around another arithmetic expansion.
The CPU calculation in the original script is only a snapshot of the counters in /proc/stat, so it isn’t really measuring usage over time. For a more meaningful percentage, read the CPU counters twice and compare the differences, or cache the previous values between iterations. Also, make the awk patterns explicit, such as /^cpu /, /^MemTotal:/, and /^MemAvailable:/, so you don’t accidentally match unrelated lines.
You’re reading /proc/meminfo twice and launching awk twice just to produce two values that are immediately displayed together. One awk invocation can collect MemTotal and MemAvailable, format both values, and exit as soon as it has found them. That reduces the work and makes the status-bar update easier to follow. There’s no real need for eval here either; keeping the formatted result in one MEM variable is safer and simpler.
Here’s a cleaner overall structure: use a Bash arithmetic for-loop, refresh the slower values when count % 50 == 0, check for DWM with pgrep when count % 25 == 0, and keep the volume update in the fast loop. Bash’s printf can format the date without spawning date: printf -v TIME '%(%m/%d %H:%M)T' -1. You can also let the caller decide whether to run the script in the background instead of putting an unconditional & at the end.
I tried adapting the suggestions to dash, but the date formatting and arithmetic syntax differ there. I’ll compare both versions and decide whether keeping Bash is worthwhile.

Good point about eval. I only used separate variables because I started with two independent calculations, but combining them into one formatted value makes more sense.