64

I'm now doing it this way:

[root@~]# echo Aa|hexdump -v
0000000 6141 000a                              
0000003
[root@~]# echo -e "\x41\x41\x41\x41"
AAAA

But it's not exactly behaving as I wanted,

the hex form of Aa should be 4161,but the output is 6141 000a,which seems not making sense.

and when performing hex to ascii,is there another utility so that I don't need the prefix \x ?

gdb
  • 7,189
  • 12
  • 38
  • 36

15 Answers15

75

The reason is because hexdump by default prints out 16-bit integers, not bytes. If your system has them, hd (or hexdump -C) or xxd will provide less surprising outputs - if not, od -t x1 is a POSIX-standard way to get byte-by-byte hex output. You can use od -t x1c to show both the byte hex values and the corresponding letters.

If you have xxd (which ships with vim), you can use xxd -r to convert back from hex (from the same format xxd produces). If you just have plain hex (just the '4161', which is produced by xxd -p) you can use xxd -r -p to convert back.

Random832
  • 37,415
  • 3
  • 44
  • 63
  • `xxd -p -r AAA`,this doesn't work,can it retrieve parameters from command line directly? – gdb Apr 20 '11 at 03:49
  • 12
    no... and the 'r' converts back from hex, you'd want something like '`echo 4161 | xxd -r -p`' or '`echo Aa | xxd -p`' – Random832 Apr 20 '11 at 04:04
  • Just FYI `xxd` is broken as of now. It desplays all zeroes instead of data. Maybe specific to my setup (xxd 2021-10-22, Ubuntu 22.04, large files > 2Gb), but anyway you should be aware of that (I lost some time to figure out what's going on). – midenok Jul 29 '22 at 13:48
31

For the first part, try

echo Aa | od -t x1

It prints byte-by-byte

$ echo Aa | od -t x1
0000000 41 61 0a
0000003

The 0a is the implicit newline that echo produces.

Use echo -n or printf instead.

$ printf Aa | od -t x1
0000000 41 61
0000002
Mikel
  • 24,855
  • 8
  • 65
  • 66
22

For single line solution:

echo "Hello World" | xxd -ps -c 200 | tr -d '\n'

It will print:

48656c6c6f20576f726c640a

or for files:

cat /path/to/file | xxd -ps -c 200 | tr -d '\n'

For reverse operation:

echo '48656c6c6f20576f726c640a' | xxd -ps -r

It will print:

Hello World
Fırat Küçük
  • 5,613
  • 2
  • 50
  • 53
22
$> printf "%x%x\n" "'A" "'a"
4161
bash-o-logist
  • 6,665
  • 1
  • 17
  • 14
  • 1
    @gdb: See [printf](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html) where it 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." – Dennis Williamson May 30 '12 at 14:17
  • 2
    The c-style `printf` solution here should be the accepted answer. It is the most portable and the most simple, and keeps with POSIX compliance without needing external tools that may or may not be available. – Yokai Oct 30 '17 at 07:41
4

With bash :

a=abcdefghij    
for ((i=0;i<${#a};i++));do printf %02X \'${a:$i:1};done

6162636465666768696A

Vouze
  • 1,678
  • 17
  • 10
  • wrong output for some characters like (space, tab, \r,\n) all of these characters will be shown as \x00 – Giac Oct 26 '17 at 12:12
4

I use:

> echo Aa | tr -d '\n' | xxd -p
4161

> echo 414161 | tr -d '\n' | xxd -r -p
AAa

The tr -d '\n' will trim any possible newlines in your input

stelios
  • 2,679
  • 5
  • 31
  • 41
2
Text2Conv="Aa"
for letter in $(echo "$Text2Conv" | sed "s/\(.\)/'\1 /g");do printf '%x' "$letter";done

4161

The trick is using sed to parse the Text2Conv to format we can then seperate anf loop using for.

SteinAir
  • 96
  • 3
2

Finally got the correct thing

echo "Hello, world!" | tr -d '\n' | xxd -ps -c 200
P1ratRuleZZZ
  • 144
  • 2
  • 7
2

I don't know how it crazy it looks but it does the job really well

ascii2hex(){ a="$@";s=0000000;printf "$a" | hexdump | grep "^$s"| sed s/' '//g| sed s/^$s//;}

Created this when I was trying to see my name in HEX ;) use how can you use it :)

Kundan Kumar
  • 104
  • 1
  • 2
1

here a little script I wrote to convert ascii to hex. hope it helps:

echo '0x'"`echo 'ASCII INPUT GOES HERE' | hexdump -vC |  awk 'BEGIN {IFS="\t"} {$1=""; print }' | awk '{sub(/\|.*/,"")}1'  | tr -d '\n' | tr -d ' '`" | rev | cut -c 3- | rev
1

SteinAir's answer above was helpful to me -- thank you! And below is a way it inspired, to convert hex strings to ascii:

for h in $(echo "4161" | sed "s/\(..\)/\1 /g"); do printf `echo "\x$h"`;done
Aa
scoombs
  • 11
  • 2
1
echo -n Aa | hexdump -e '/1 "%02x"'; echo
baz
  • 1,317
  • 15
  • 10
0

according to http://mylinuxbook.com/hexdump/ you might use the hexdump format parameter

echo Aa | hexdump -C -e '/1 "%02X"'

will return 4161

to add an extra linefeed at the end, append another formatter.

BUT: the format given above will give multiplier outputs for repetitive characters

$ printf "Hello" | hexdump -e '/1 "%02X"' 
48656C*
6F

instead of

48656c6c6f
childno͡.de
  • 4,679
  • 4
  • 31
  • 57
0
jcomeau@aspire:~$ echo -n The quick brown fox jumps over the lazy dog | python -c "print raw_input().encode('hex'),"
54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67
jcomeau@aspire:~$ echo -n The quick brown fox jumps over the lazy dog | python -c "print raw_input().encode('hex')," | python -c "print raw_input().decode('hex'),"
The quick brown fox jumps over the lazy dog

it could be done with Python3 as well, but differently, and I'm a lazy dog.

jcomeau_ictx
  • 37,688
  • 6
  • 92
  • 107
-1

echo append a carriage return at the end.

Use

echo -e

to remove the extra 0x0A

Also, hexdump does not work byte-per-byte as default. This is why it shows you bytes in a weird endianess and why it shows you an extra 0x00.