using bash: write bit representation of integer to file
Solution 1
You can use echo to emit specific bytes using hex or octal. For example:
echo -n -e \\x30
will print ascii 0 (0x30)
(-n remove trailing newline)
Solution 2
printf
is more portable than echo
. This function takes a decimal integer and outputs a byte with that value:
echobyte () {
if (( $1 >= 0 && $1 <= 255 ))
then
printf "\\x$(printf "%x" $1)"
else
printf "Invalid value\n" >&2
return 1
fi
}
$ echobyte 97
a
$ for i in {0..15}; do echobyte $i; done | hd
00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................|
00000010
Solution 3
xxd
is the better way. xxd -r infile outfile
will take ascii hex-value in infile to patch outfile, and you can specify the specific position in infile by this: 1FE:55AA
Solution 4
I have a function to do this:
# number representation from 0 to 255 (one char long)
function chr() { printf "\\$(printf '%03o' "$1")" ; return 0 ; }
# from 0 to 65535 (two char long)
function word_litleendian() { chr $(($1 / 256)) ; chr $(($1 % 256)) ; return 0 ; }
function word_bigendian() { chr $(($1 % 256)) ; chr $(($1 / 256)) ; return 0 ; }
# from 0 to 4294967295 (four char long)
function dword_litleendian() { word_lilteendian $(($1 / 65536)) ; word_litleendian $(($1 % 65536)) ; return 0 ; }
function dword_bigendian() { word_bigendian $(($1 / 65536)) ; word_bigendian $(($1 % 65536)) ; return 0 ; }
You can use piping or redirection to catch the result.
Solution 5
Worked like a treat. I used the following code to replace 4 bytes at byte 24 in little endian with two integers (1032 and 1920). The code does not truncate the file.
echo -e \\x08\\x04\\x80\\x07 | dd of=<file> obs=1 oseek=24 conv=block,notrunc cbs=4
Thanks again.
Max Leske
Updated on June 05, 2022Comments
-
Max Leske almost 2 years
I have a file with binary data and I need to replace a few bytes in a certain position. I've come up with the following to direct bash to the offset and show me that it found the place I want:
dd bs=1 if=file iseek=24 conv=block cbs=2 | hexdump
Now, to use "file" as the output:
echo anInteger | dd bs=1 of=hextest.txt oseek=24 conv=block cbs=2
This seems to work just fine, I can review the changes made in a hex editor. Problem is, "anInteger" will be written as the ASCII representation of that integer (which makes sense) but I need to write the binary representation.
I want to use bash for this and the script should run on as many systems as possible (I don't know if the target system will have python or whatever installed).
How do I tell the command to convert the input to binary (possibly from a hex)?
-
Max Leske almost 14 yearsThis seems to work. I'll try to figure it out and post my results.
-
Max Leske almost 14 yearsI thought of that but I don't want to use an extra file for 4 bytes.
-
Max Leske almost 14 yearsI tried it out. Your code will return a binary which will be written to the file as the ASCII representation of that binary. Nice thought though, thanks.
-
Max Leske almost 14 yearsSweet! But as you can see in my answer below, that would probably be overkill. Still, nice to know.
-
Gordon Davisson almost 14 yearsecho is disturbingly nonportable -- for the example above, some implementations will just print
-e \x30
, which isn't what you want at all. -
Gordon Davisson almost 14 yearsIf you know the integer(s) in advance, you can simplify this quite a bit, e.g.
printf "\x30"
-
SourceSeeker almost 14 years@Gordon: That's true see the OP's answer. However, the whole purpose of this function is versatility.
-
Max Leske almost 14 yearsWeird, wouldn't have thought so. Luckily the script is already running without problems.
-
starfry over 9 yearswhy, oh why, isn't there a simple way to do this with decimal numbers? I'm converting to hex first -
echo -ne \\x$(printf '%x' 65)
surely there has to be a better way...? -
Jérôme Pouiller almost 6 yearsI suggest to use
printf
instead ofecho -n -e
:printf \\x30
-
Maarten Bodewes over 2 yearsBeware of the many problems with
echo
portability; it seems to be a serious thing.printf
should be considered most of the time. -
Max Leske over 2 yearsCorrect. This was already mentioned by @Dennis Williamson in a separate answer: stackoverflow.com/a/2747374/219324
-
MayeulC over 2 yearsI would like to note that endianness conversion has been done manually in that answer.