How to write binary data in Bash
You can write arbitrary bytes in hex or octal format with:
printf '\x03' > file # Hex
printf '\003' > file # Octal
If you have binary, this is a bit tricky, but you can turn it to octal with:
printf '%o\n' "$((2#00000011))"
which of course can be nested in the following:
binary=00000011
printf "\\$(printf '%o' "$((2#$binary))")" > file
Note that this only works with 8 bits. If you want to write longer values, you need to split them into groups of 8.
source to share
Just use %b
in printf:
printf "%b" "\012"
printf "%b" "\x0a"
% b - print the associated argument when interpreting the backslash goes there
so above both printable characters is the binary value for the decimal 10
.
printf "%b" "\x0a" | od -bc
Output
0000000 012
\n
you can even mix
printf "%b" "\12\xa\n" | od -bc
0000000 012 012 012
\n \n \n
source to share
More often than not, you want to write a template (like a 32 bit template).
# Write 32 bits 5 times to a file
for i in {1..5}
do
printf '\x12\x34\xAC\xCD' >> binaryfile.bin
done
Another example:
for i in {1..255}
do
hx=$( printf "%x" $i )
output="\x$hx\x00\x00\x00"
printf "%b" $output >> binaryfile.bin
done
source to share
Using bc (on CentOS 7.4):
VALUE="3F"
INPUT_BASE=16
OUTPUT_BASE=2
printf "%b\n" $(bc <<< "ibase=$INPUT_BASE; obase=$OUTPUT_BASE; $VALUE")
RESULT : 111111
If leading zeros are needed then:
VALUE="3F"
INPUT_BASE=16
OUTPUT_BASE=2
printf "%16b\n" $(bc <<< "ibase=$INPUT_BASE; obase=$OUTPUT_BASE; $VALUE") | sed 's^ ^0^g'
RESULT : 0000000000111111
Note the use of 16 in printf format; change the value to limit the leading zero
source to share
A couple of more general functions for printing integers to a file:
le16 () { # little endian 16 bit; 1st param: integer to 2nd param: file
v='awk -v n=$1 'BEGIN{printf "%04X", n;}''
echo -n -e "\\x${v:2:2}\\x${v:0:2}" >> $2
}
le32 () { # 32 bit version
v='awk -v n=$1 'BEGIN{printf "%08X", n;}''
echo -n -e "\\x${v:6:2}\\x${v:4:2}\\x${v:2:2}\\x${v:0:2}" >> $2
}
source to share