Bash Scripting – How to Get 0-Padded Numbers in {} (Brace Expansion)

bashforscripting

I'm trying to write a simple script to retrieve mem and swap usage from a list of hosts. Currently the only way I've been able to achieve this is to write 3 seperate scripts:

for a in {1..9}; do echo "bvrprdsve00$a; $(ssh -q bvrprdsve00$a "echo \$(free -m|grep Mem|/bin/awk '{print \$4}';free -m|grep Swap|/bin/awk '{print \$4}')")"; done > /tmp/svemem.txt;
for a in {10..99}; do echo "bvrprdsve0$a; $(ssh -q bvrprdsve0$a "echo \$(free -m|grep Mem|/bin/awk '{print \$4}';free -m|grep Swap|/bin/awk '{print \$4}')")"; done >> /tmp/svemem.txt;
for a in {100..218}; do echo "bvrprdsve$a; $(ssh -q bvrprdsve$a "echo \$(free -m|grep Mem|/bin/awk '{print \$4}';free -m|grep Swap|/bin/awk '{print \$4}')")"; done >> /tmp/svemem.txt

The reason for this is that the hostname always ends in a 3 digit number and these hosts go from 001-218 so I've needed to do a different for loop for each set (001-009, 010-099, 100-218). Is there a way in which I can do this in one script instead of joining 3 together?

Best Answer

Bash brace expansions could generate the numbers with leading zeros (since bash 4.0 alpha+ ~2009-02-20):

$ echo {001..023}
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023

So, you can do:

for a in {001..218}; do  echo "bvrprdsve$a; $(ssh -q bvrprdsve$a "echo \$(free -m|grep Mem|/bin/awk '{print \$4}';free -m|grep Swap|/bin/awk '{print \$4}')")"; done >> /tmp/svemem.txt

But, let's look inside the command a little bit:

  1. You are calling free twice, using grep and then awk:

    free -m|grep Mem |/bin/awk '{print \$4}';
    free -m|grep Swap|/bin/awk '{print \$4}'
    

    All could be reduced to this one call to free and awk:

    free -m|/bin/awk '/Mem|Swap/{print \$4}'
    
  2. Furthermore, the internal command could be reduced to this value:

    cmd="echo \$(free -m|/bin/awk '/Mem|Swap/{print \$4}')"
    

Then, the whole script will look like this:

b=bvrprdsve;
f=/tmp/svemem.txt;
cmd="echo \$(free -m|/bin/awk '/Mem|Swap/{print \$4}')";
for a in {001..218}; do echo "$b$a; $(ssh -q "$b$a" "$cmd")"; done >> "$f";
Related Question