Originally published on the old depletionmode / 2of1 blog (archived copy).
I came across a one-liner for printing a byte in binary embedded in an article on AVR fuses (http://electrons.psychogenic.com/modules/arms/art/14/AVRFusesHOWTOGuide.php).
I’ve extended this one-liner to output all bytes of a target in binary:
od -t u1 /tmp/target | \
cut -d' ' -f2- | \
perl -ane 'foreach(@F) { $byte = unpack("B32", pack("N",$_)); $byte =~ s/.*([01]{4})([01]{4})$/$1 $2/; print $byte, "\n"; }'Let me break that up.
od is a utility that allows bytes from a file to be output in a number of different types. In this case we want each byte to be output as an unsigned decimal value so we provide the ‘-t u1′ option:
$ od -t u1 /tmp/target
0000000 0 17 34 51 68 85 102 119 136 153 170 187 204 221 238 255
0000020 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0000040The first thing we need to do is trim off the offset in the first column. We can do this in a number of ways. Here I’ve chosen the cut utility. This utility works more-or-less like the ’split’ or tokanisation commands we commonly use in coding.
We provide a delimiter for performing the cut, with -d’ ‘ (splitting on a ’space’). The ‘-s’ option cuts all lines that have no ‘delimiter’. As we’re trying to get rid of the first field (the offset), we want cut to return all fields excluding the first. We do this with ‘-f2-’, i.e. give us from field number 2 onwards:
$ od -t u1 /tmp/target | cut -s -d' ' -f2-
0 17 34 51 68 85 102 119 136 153 170 187 204 221 238 255
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15Now we can use perl to perform the rest of the work:
$ od -t u1 /tmp/target | cut -d' ' -f2- | perl -ane 'foreach(@F) { $byte = unpack("B32", pack("N",$_)); $byte =~ s/.*([01]{4})([01]{4})$/$1 $2/; print $byte, "\n"; }'
0000 0000
0001 0001
0010 0010
0011 0011
0100 0100
0101 0101
0110 0110
0111 0111
1000 1000
1001 1001
1010 1010
1011 1011
1100 1100
1101 1101
1110 1110
1111 1111
0000 0000
0000 0001
0000 0010
0000 0011
0000 0100
0000 0101
0000 0110
0000 0111
0000 1000
0000 1001
0000 1010
0000 1011
0000 1100
0000 1101
0000 1110
0000 1111
0010 1000First lets explain the perl command line options:
- -a – this causes all command arguments to be automatically split (delimited by ‘ ‘) and placed in the array @F
- -n – this causes perl to loop around all command arguments and execute for each argument
- -e – allows to script to be passed to perl on the command line
Now for the perl script itself:
foreach(@F) {
$byte = unpack("B32", pack("N",$_));
$byte =~ s/.*([01]{4})([01]{4})$/$1 $2/;
print $byte, "\n"; }First we loop through each item in @F; in this case each byte in decimal output by od.
For each byte we need to unpack it; i.e. convert it into a binary printable format.
We then use a regex to cause only 8 bits to be present, each nibble separated by a space.
Finally we print the byte.