views:

281

answers:

5

Hullo

First, 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).

Here's the problem: 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.

How do I tell the command to convert the input to binary (possibly from a hex)?

A: 

If you're willing to rely on bc (which is fairly common)

echo -e "ibase=16\n obase=2 \n A1" | bc -q

might help.

nc3b
I 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.
theseion
A: 

You might put the desired input into a file and use the "if=" option to dd to insert exactly the input you desire.

WhirlWind
I thought of that but I don't want to use an extra file for 4 bytes.
theseion
+2  A: 

You can use echo to emit specific bytes using hex or octal. For example:

echo -e \\x30 

will print ascii 0 (0x30)

cs80
This seems to work. I'll try to figure it out and post my results.
theseion
echo is disturbingly nonportable -- for the example above, some implementations will just print `-e \x30`, which isn't what you want at all.
Gordon Davisson
Weird, wouldn't have thought so. Luckily the script is already running without problems.
theseion
+3  A: 

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
Dennis Williamson
Sweet! But as you can see in my answer below, that would probably be overkill. Still, nice to know.
theseion
If you know the integer(s) in advance, you can simplify this quite a bit, e.g. `printf "\x30"`
Gordon Davisson
@Gordon: That's true see the [OP's answer](http://stackoverflow.com/questions/2746707/using-bash-write-bit-representation-of-integer-to-file/2747396#2747396). However, the whole purpose of this function is versatility.
Dennis Williamson
A: 

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.

theseion