Awk and Grep Battery DesignCapacity for Intel MacBooks

bkruger
New Contributor II

Hey Nation :-)

So here's a challenge for the scripting guru's...

I'm trying to write an EA for getting the Design Capacity for a built-in Intel MacBook Pro battery.

So far I have this script:

/usr/sbin/ioreg -r -c "AppleSmartBattery" | /usr/bin/grep -w "DesignCapacity" | /usr/bin/awk '{print $3}'

But this yields me waaaaaay too much info and the required awk value is on it's own new line right at the bottom.

The body of the result output does contain the "DesignCapacity" value mixed in among hundreds of other values!

So my challenge is... how do I get rid of all that extra value output to just have the final line output?

eg:

me@MacBookPro ~ % /usr/sbin/ioreg -r -c "AppleSmartBattery" | /usr/bin/grep -w "DesignCapacity" | /usr/bin/awk '{print $3}'

gives this result:                

{"PMUConfigured"=0,"FccComp2"=5050,"ResScale"=133,"SystemPower"=1051098690,"Qmax"=(5496,5497,5510),"DesignCapacity"=5103,"CellVoltage"=(4169,4169,4169),"PassedCharge"=26,"RaTableRaw"=(<00550070005f007300780084006c0074007c007f0082007a009000da0179024e>,<000000650055006100660072005d0065006c007100760072008800ca0168022f>,<0000006c005c006e0073007e0067006e00760079007c0074008a00d20173023e>),"StateOfCharge"=88,"PresentDOD"=(12,12,12),"Flags"=557318657,"DataFlashWriteCount"=3462,"DOD0"=(2080,2096,2080),"ChemID"=9216,"AdapterPower"=0,"CycleCount"=9,"Voltage"=12511,"GaugeFlagRaw"=192,"FccComp1"=5168,"BatteryState"=<000000000000000043e4000202000000>,"ManufactureDate"=52987870328882,"LifetimeData"={"TotalOperatingTime"=14205,"UpdateTime"=1664774348,"AverageTemperature"=0,"TimeAtHighSoc"=<58000000cb0100000300000000000000>},"Serial"="F5D01130MLSKGGJBB"}

5103

me@MacBookPro ~ % 

(the number "5103" is the value I am after...)

Thanks y'awl for any help and comments - but be gentle... it's my first post! :-)

 

 

2 ACCEPTED SOLUTIONS

dwbergstrom
New Contributor III

There's probably a way to consolidate the two cut commands at the end of this, but it has worked for me:

/usr/sbin/ioreg -i -w 0 -f -r -c AppleSmartBattery | /usr/bin/grep "BatteryData" | /usr/bin/grep -o 'DesignCapacity.*' | /usr/bin/cut -f2- -d"=" | /usr/bin/cut -f1 -d","

View solution in original post

brockwalters
Contributor II

@bkruger @dwbergstrom Please just learn to correctly use the ioreg options. Parsing is built-in to the ioreg binary. The reason you should do this instead of awk / grep / sed is that system values may change & your sketchy parsing may stop working. If you actually use the structure in the data provided by something like ioreg your EAs will probably have a longer shelf life. 

In the ioreg command posted above the -w 0 makes absolutely no difference. Limiting the width is unneeded & is not meant for parsing, only for reading.

The only line in the output changed by the "smart formatting" -f flag is the "manufacture data" key / val which you aren't using. Totally useless.

The inheritance flag -i is, again, totally useless as all it is doing is showing class names above the object at the top of the output.

So, what you are left with that is actually meaningful is the following:

 

 /usr/sbin/ioreg -r -c AppleSmartBattery

 

This obtains the "root" (-r) of the "class" (-c) AppleSmartBattery.

To use PlistBuddy to get the key/val you want in the data ("BatteryData") use the -a option for "archive" format:

 

% /usr/libexec/PlistBuddy -c "print 0:BatteryData:DesignCapacity" /dev/stdin <<< "$(/usr/sbin/ioreg -ar -c AppleSmartBattery)"                                      
5103

 

View solution in original post

9 REPLIES 9

dwbergstrom
New Contributor III

There's probably a way to consolidate the two cut commands at the end of this, but it has worked for me:

/usr/sbin/ioreg -i -w 0 -f -r -c AppleSmartBattery | /usr/bin/grep "BatteryData" | /usr/bin/grep -o 'DesignCapacity.*' | /usr/bin/cut -f2- -d"=" | /usr/bin/cut -f1 -d","

bkruger
New Contributor II

dwbergstom!! You are da man!

Kudos - never thought to use the cut command! Here I was messing about with sed... :-)

But thank you very much - the bonus is that it also works with Apple Silicon too!

(and the battery output from Silicon MacBooks has 10x more values!)

Thank You again.

Jamf Nation and Jamf Community Rocks. √

dwbergstrom
New Contributor III

Sure thing!  I had the scenario of needing this to work on both Apple Silicon and Intel, so this is what ended up working out.  Glad it's helpful!

brockwalters
Contributor II

@bkruger @dwbergstrom Please just learn to correctly use the ioreg options. Parsing is built-in to the ioreg binary. The reason you should do this instead of awk / grep / sed is that system values may change & your sketchy parsing may stop working. If you actually use the structure in the data provided by something like ioreg your EAs will probably have a longer shelf life. 

In the ioreg command posted above the -w 0 makes absolutely no difference. Limiting the width is unneeded & is not meant for parsing, only for reading.

The only line in the output changed by the "smart formatting" -f flag is the "manufacture data" key / val which you aren't using. Totally useless.

The inheritance flag -i is, again, totally useless as all it is doing is showing class names above the object at the top of the output.

So, what you are left with that is actually meaningful is the following:

 

 /usr/sbin/ioreg -r -c AppleSmartBattery

 

This obtains the "root" (-r) of the "class" (-c) AppleSmartBattery.

To use PlistBuddy to get the key/val you want in the data ("BatteryData") use the -a option for "archive" format:

 

% /usr/libexec/PlistBuddy -c "print 0:BatteryData:DesignCapacity" /dev/stdin <<< "$(/usr/sbin/ioreg -ar -c AppleSmartBattery)"                                      
5103

 

bkruger
New Contributor II

@brockwalters - you are also da man!

It's so good to get such helpful and very specific guidance on this forum. Jamf Nation! I'm a fan!

I think firstly I have to say thank you to @dwbergstrom for exactly answering my OP and question - he did indeed give me the correct syntax that I was looking for to sort through the std output.

And then I have to give extra thanks to @brockwalters for some very good advice and guidelines on setting up EA and future-proofing them! It's a great approach to check the plist file and use the key values instead!!

So in the end, not just did I get my original script working, but I was also schooled in a better way to get it (and future EA's) working... Thank you both guys  

Tinkster
New Contributor

And if you have homebrew and GNU sed handy:



/usr/sbin/ioreg -i -w 0 -f -r -c AppleSmartBattery|gsed -nE '/BatteryData/{s/^.+DesignCapacity.=//;s/,.*$//p } '

 

For some reason the OS/X sed doesn't like the curly braces, even though the manual claims that they work for grouping =/

 

And w/o foreign help:

 

/usr/sbin/ioreg -i -w 0 -f -r -c AppleSmartBattery|/usr/bin/awk '/BatteryData/{sub(/^.+DesignCapacity"=/,"");sub(/,.+$/,"");print}'

 

brockwalters
Contributor II

@Tinkster Again, why? The output of ioreg with -a is a plist. On macOS, that's a native format which you can parse with PlistBuddy. Why do you think offering a way to do this that isn't native & that requires a GNU version of a binary that isn't native is somehow equivalent or better? It's not. Why do you think using awk is better? It's not. PlistBuddy lets you use the semi-structured data to get right to the key / value you need.

@brockwalters 

The `awk` used above comes w/ the OS, it's not the GNU version.

Plistbuddy doesn't. 

Why shouldn't I be using what I have ready available?

@Tinkster 

PlistBuddy is part of macOS... /usr/libexec/PlistBuddy

gsed is not native nor did I say awk wasn't native. Reading for comprehension is a powerful skill...


As for your question: parsing semi-structured data using key/value pairs is always better & more precise & more future proof than bash %*@&ery. That’s why.