Let us say there is a variable in bash script with value \"001\" how can i write this binary data into a file as bits (as \"001\" not \"1\") echo writes it as string but i w
Using bc (in 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 the printf format; change value to limit leading-zero count
A couple of more general functions to output 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
}
Just use the %b
in the printf:
printf "%b" "\012"
printf "%b" "\x0a"
%b - Print the associated argument while interpreting backslash escapes in there
so, above both prints 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
You can write arbitrary bytes in hex or octal with:
printf '\x03' > file # Hex
printf '\003' > file # Octal
If you have binary, it's a bit tricker, but you can turn it into octal with:
printf '%o\n' "$((2#00000011))"
which of course can be nested in the above:
binary=00000011
printf "\\$(printf '%o' "$((2#$binary))")" > file
Note that this only works with up to 8 bits. If you want to write longer values, you have to split it up into groups of 8.
Most often you want to write a pattern (for instance a 32 bit pattern).
# 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
I needed this recently, someone might find it useful :
#!/bin/bash
# generate bitmasks for a C array
# loop counter
NUMBER=0
MAX_BITMASK_LENGTH=8
# max loop value : 2^8 = 255
MAXVAL=$((2**MAX_BITMASK_LENGTH))
# line number
LINE=0
# echo start of C array
echo " const long int bitmasks[${MAX_BITMASK_LENGTH}] = {"
# loop over range of values
while [ ${NUMBER} -le ${MAXVAL} ] ; do
# use bc to convert to binary
BINARY=`echo -e "obase=2\n${NUMBER}"| bc`
# print current number, linenumber, binary
printf "%12s, /* (%i) %8s */\n" ${NUMBER} ${LINE} ${BINARY}
# increase loop value to next value
NUMBER=$(((NUMBER*2)+1))
# increment line number
LINE=$((LINE+1))
done
# echo end of C array
echo " };"
This outputs:
$ ./generate_bitmasks.sh
const long int bitmasks[8] = {
0, /* (0) 0 */
1, /* (1) 1 */
3, /* (2) 11 */
7, /* (3) 111 */
15, /* (4) 1111 */
31, /* (5) 11111 */
63, /* (6) 111111 */
127, /* (7) 1111111 */
255, /* (8) 11111111 */
};