How do I iterate through each line of a command's output in bash?

bash

Solution

Change this line in the middle of your loop:

IFS=' ' cpu=($cpu)

You need this because outside of your loop you're setting `IFS=$'\n', but with that setting`cpu($cpu)` won't do what you expect.

Btw, I would write your script like this:

#!/bin/bash -e

grep ^cpu /proc/stat | while IFS=$'\n' read cpu; do
    cpu=($cpu)
    name=${cpu[0]}
    unset cpu[0]
    idle=${cpu[4]}
    total=0
    for value in "${cpu[@]}"; do
        ((total+=value))
    done
    ((usage=(1000 * (total - idle) / total + 5) / 10))
    echo "$name $usage%"
done

The equivalent using `awk`:

awk '/^cpu/ { total=0; idle=$5; for (i=2; i<=NF; ++i) { total += $i }; print $1, int((1000 * (total - idle) / total + 5) / 10) }' < /proc/stat

Problem

I have a script that reads from `/proc/stat` and calculates CPU usage. There are three relevant lines in `/proc/stat`: ``` cpu 1312092 24 395204 12582958 77712 456 3890 0 0 0 cpu0 617029 12 204802 8341965 62291 443 2718 0 0 0 cpu1 695063 12 190402 4240992 15420 12 1172 0 0 0 ``` Currently, my script only reads the first line and calculates usage from that: ``` cpu=($( cat /proc/stat | grep '^cpu[^0-9] ' )) unset cpu[0] idle=${cpu[4]} total=0 for value in "${cpu[@]}"; do let total=$(( total+value )) done let usage=$(( (1000*(total-idle)/total+5)/10 )) echo "$usage%" ``` This works as expected, because the script only parses this line: ``` cpu 1312092 24 395204 12582958 77712 456 3890 0 0 0 ``` It's easy enough to get only the lines starting with `cpu0` and `cpu1` ``` cpu=$( cat /proc/stat | grep '^cpu[0-9] ' ) ``` but I don't know how to iterate over each line and apply this same process. Ive tried resetting the internal field separator inside a subshell, like this: ``` cpus=$( cat /proc/stat | grep '^cpu[0-9] ' ) ( IFS=$'\n' for cpu in $cpus; do cpu=($cpu) unset cpu[0] idle=${cpu[4]} total=0 for value in "${cpu[@]}"; do let total=$(( total+value )) done let usage=$(( (1000*(total-idle)/total+5)/10 )) echo -n "$usage%" done ) ``` but this gets me a syntax error ``` line 18: (1000*(total-idle)/total+5)/10 : division by 0 (error token is "+5)/10 ") ``` If I echo the `cpu` variable in the loop it looks like it's separating the lines properly. I looked at this thread and I think Im assigning the cpu variable to an array properly but is there another error Im not seeing? I put my script into whats wrong with my script and it doesnt show me any errors apart from a warning about using `cat` within `$()`, s o I'm stumped.

Original source

Related problems