Search code examples
bashhexhexdumpxxd

How to convert hex to ASCII while preserving non-printable characters


I've been experiencing some weird issues today while debugging, and I've managed to trace this to something I overlooked at first.

Take a look at the outputs of these two commands:

root@test:~# printf '%X' 10 | xxd -r -p | xxd -p
root@test:~# printf '%X' 43 | xxd -r -p | xxd -p
2b
root@test:~#

The first xxd command converts hex to ASCII. The second converts ASCII back to hex. (43 decimal = 2b hex).

Unfortunately, it seems that converting hex to ASCII does not preserve non-printable characters. For example, the raw hex "A" (10 decimal = A hex), somehow gets eaten up by xxd -r -p. Thus, when I perform the inverse operation, I get an empty result.

What I am trying to do is feed some data into minimodem. I need to generate Call Waiting Caller ID (FSK), effectively via bit banging. My bash script has the right bits, but if I do a hexdump, the non-printable characters are missing. Unfortunately, it seem that minimodem only accepts ASCII characters, and I need to feed it raw hex, but it seems that gets eaten up in the conversion. Is it possible to preserve these characters somehow? I don't see it as any option, so wondering if there's a better way.


Solution

  • xxd expects two characters per byte. One A is invalid. Do:

    printf '%02X' 10 | xxd -r -p | xxd -p
    

    How to convert hex to ASCII while preserving non-printable characters

    Use xxd. If your input has one character, pad it with an initial 0.

    ASCII does not preserve non-printable characters

    It does preserve any bytes, xxd is the common tool to work with any binary data in shell.

    Is it possible to preserve these characters somehow?

    Yes - input sequence of two characters per byte to xxd.