How to Create a Hex Dump of File Containing Only the Hex Characters Without Spaces in Bash

How to print only the hex values from hexdump without the line numbers or the ASCII table?

You can specify the exact format that you want hexdump to use for output, but it's a bit tricky. Here's the default output, minus the file offsets:

hexdump -e '16/1 "%02x " "\n"' file.bin

(To me, it looks like this would produce an extra trailing space at the end
of each line, but for some reason it doesn't.)

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

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.

Show Hexadecimal Numbers Of a File

Edit: Added "bytestream" functionality. If the script name contains the word "stream" (e.g. it's a symlink such as ln -s bash-hexdump bash-hexdump-stream and run as ./bash-hexdump-stream), it will output a continuous stream of hex characters representing the contents of the file. Otherwise its output will look like hexdump -C.

It takes a bunch of trickery since Bash isn't really good at binary:

#!/bin/bash
# bash-hexdump
# by Dennis Williamson - 2010-01-04
# in response to http://stackoverflow.com/questions/2003803/show-hexadecimal-numbers-of-a-file
# usage: bash-hexdump file

if [[ -z "$1" ]]
then
exec 3<&0 # read stdin
[[ -p /dev/stdin ]] || tty="yes" # no pipe
else
exec 3<"$1" # read file
fi

# if the script name contains "stream" then output will be continuous hex digits
# like hexdump -ve '1/1 "%.2x"'
[[ $0 =~ stream ]] && nostream=false || nostream=true

saveIFS="$IFS"
IFS="" # disables interpretation of \t, \n and space
saveLANG="$LANG"
LANG=C # allows characters > 0x7F
bytecount=0
valcount=0
$nostream && printf "%08x " $bytecount
while read -s -u 3 -d '' -r -n 1 char # -d '' allows newlines, -r allows \
do
((bytecount++))
printf -v val "%02x" "'$char" # see below for the ' trick
[[ "$tty" == "yes" && "$val" == "04" ]] && break # exit on ^D
echo -n "$val"
$nostream && echo -n " "
((valcount++))
if [[ "$val" < 20 || "$val" > 7e ]]
then
string+="." # show unprintable characters as a dot
else
string+=$char
fi
if $nostream && (( bytecount % 8 == 0 )) # add a space down the middle
then
echo -n " "
fi
if (( bytecount % 16 == 0 )) # print 16 values per line
then
$nostream && echo "|$string|"
string=''
valcount=0
$nostream && printf "%08x " $bytecount
fi
done

if [[ "$string" != "" ]] # if the last line wasn't full, pad it out
then
length=${#string}
if (( length > 7 ))
then
((length--))
fi
(( length += (16 - valcount) * 3 + 4))
$nostream && printf "%${length}s\n" "|$string|"
$nostream && printf "%08x " $bytecount
fi
$nostream && echo

LANG="$saveLANG";
IFS="$saveIFS"

The apostrophe trick is documented here. The relevant part says:

If the leading character is a
single-quote or double-quote, the
value shall be the numeric value in
the underlying codeset of the
character following the single-quote
or double-quote.

Here is some output from the script showing the first few lines of my /bin/bash plus a few more:


00000000 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 02 00 03 00 01 00 00 00 e0 1e 06 08 34 00 00 00 |............4...|
00000020 c4 57 0d 00 00 00 00 00 34 00 20 00 09 00 28 00 |.W......4. ...(.|
00000030 1d 00 1c 00 06 00 00 00 34 00 00 00 34 80 04 08 |........4...4...|
. . .
00000150 01 00 00 00 2f 6c 69 62 2f 6c 64 2d 6c 69 6e 75 |..../lib/ld-linu|
00000160 78 2e 73 6f 2e 32 00 00 04 00 00 00 10 00 00 00 |x.so.2..........|
00000170 01 00 00 00 47 4e 55 00 00 00 00 00 02 00 00 00 |....GNU.........|

Dump a ```sha``` checksum output to disk in binary format instead of plaintext hex in bash

Found it! After a bit more digging in forums / man pages, xxd is able to solve it for me (found it here: https://gist.github.com/dstebila/6194f90097c43c091dd2 ):

# Convert hex to binary using xxd's reverser in plain hexdump style
xxd -r -ps

So xxd is able to take a file filled with ASCII hexdump, and convert it to a binary content:

$ echo "48454C4C4F" > test.hex
$ xxd test.hex
00000000: 3438 3435 3443 3443 3446 0a 48454C4C4F.
$ xxd -r -ps test.hex > test.bin
$ xxd test.bin
00000000: 4845 4c4c 4f HELLO
$ ls -lrth test.hex
-rw-r--r-- 1 jrlab jrlab 11 mars 2 15:44 test.hex
$ ls -lrth test.bin
-rw-r--r-- 1 jrlab jrlab 5 mars 2 15:44 test.bin


Related Topics



Leave a reply



Submit