There is a similar tool called xxd. If you run xxd with just a file name it dumps the data in a fairly standard hex dump format:
# xxd bdata
0000000: 0001 0203 0405
......
Now if you pipe the output back to xxd with the -r option and redirect that to a new file, you can convert the hex dump back to binary:
# xxd bdata | xxd -r >bdata2
# cmp bdata bdata2
# xxd bdata2
0000000: 0001 0203 0405
Answer from Bert on Stack OverflowThere is a similar tool called xxd. If you run xxd with just a file name it dumps the data in a fairly standard hex dump format:
# xxd bdata
0000000: 0001 0203 0405
......
Now if you pipe the output back to xxd with the -r option and redirect that to a new file, you can convert the hex dump back to binary:
# xxd bdata | xxd -r >bdata2
# cmp bdata bdata2
# xxd bdata2
0000000: 0001 0203 0405
Restore file, given only the output of hexdump file
If you only have the output of hexdump file and want to restore the original file, first note that hexdump's default output depends on the endianness of the system you ran hexdump on!
If you have access to the system that created the dump, you can determinate its endianness using below command:
[[ "$(printf '\01\03' | hexdump)" == *0103* ]] && echo big || echo little
Reversing little-endian hexdump
This is the most common case. All x86/x64 systems are little-endian. If you don't know the endianness of the system that ran hexdump file, try this.
sed 's/ \(..\)\(..\)/ \2\1/g;$d' dump | xxd -r
The sed part converts hexdump's format into xxd's format, at least so far that xxd -r works.
Reversing big-endian hexdump
sed '$d' dump | xxd -r
Known Bugs (see comment section)
- A trailing null byte is added if the original file was of odd length (e.g. 1, 3, 5, 7, ..., byte long).
- Repeating sections of the original file are not restored correctly if they were
hexdumped using a*.
You can check your dump for above problematic cases by running below command:
grep -qE '^\*|^[0-9a-f]*[13579bdf] *$' dump && echo bug || echo ok
Better alternative to create hexdumps in the first place
Besides the non-posix (and therefore not so portable) xxd there is od (octal dump) which should be available on all unix-like systems as it is specified by posix:
od -tx1 -An -v
Will print a hexadecimal dump, grouping digits as single bytes (-tx1), with no Address prefixes (-An, similar to xxd -p) and without abbreviating repeated sections as * (-v). You can reverse such a dump using xxd -r -p.
You will have to write your own binary to hex function ...
cut -f2-8 -d' ' infile | tr -d '\n' | tr ' ' '\n' | while read l;
do
echo -n $(bin_to_hex($l)) >> outfile
(( ++n ))
(( n % 60 == 0)) && echo "" >> outfile
done
This should output the same format as -p which can then be run through -r.
If you read the man page for xxd you will read that there is no -r for -b. It says so on the excerpt that you included in your question.
You alter the structure of the file do you can't easy do this. Maybe something like this can help (but you will loose newline characters:
awk '{printf $8}' binary_format.txt >out_file
Perl, 122 + 54 = 176 122 + 45 = 167
The forward script:
$/=$,;for(<>=~/.{1,16}/gs){$h="";$h.=sprintf"%*s%02x",++$m%2,"",ord for/./gs;
s/[^ -~]/./g;printf"%06x0:%-42s",$n++,$h;say}
And the reverse script:
/:(.+?) /,print map{chr hex}$1=~/\w\w/gfor<>
(This one is interesting; there are all kinds of obscure bugs that can show up in the reverse script depending on the input, if you're not careful.)
Javascript, 247 + 61 = 308 225 + 63 = 288
-20 or so thanks to ASCII-only
Forward:
b=>[...Array(b.length+15>>4)].map((_,i)=>(P=j=>i=>i.toString(x=16).padStart(j,0))(7)(i)+"0: "+(p=b.splice(0,x)).map(P(2)).join``.replace(/.{4}/g,"$& ").padEnd(42)+p.map(l=>String.fromCharCode(l>31&l<127?l:46)).join``).join`
`
Try it online!
Reverse:
d=>d.match(/[^:]{40}/g).join``.match(/\S\S/g).map(t=>+("0x"+t))
Try it online!
Might make an explanation at some point.
There's no one command that I know of that will do the conversion, but it can easily be broken up into a few steps:
- Strip addresses from
hexdumpoutput usingsed - Convert into binary using
xxd - Endian conversion (for example,
5a42becomes425a) usingdd
Here's the full command:
sed 's/^[0-9]*//' hexdump | xxd -r -p | dd conv=swab of=binaryfile
Try to add -p.
xxd -r -p hexdumpfile > binaryfile