15

I converted a simple binary file into a text file with:

od –t x1 Check.tar | cut –c8- > Check.txt

Which gives a content similar to:

 64 65 76 2f 6e 75 6c 6c 00 00 00 00 00 00 00 00
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 [...]

What is the opposite way -- to convert Check.txt to Check.tar as the original file?

Jeff Schaller
  • 66,199
  • 35
  • 114
  • 250
maihabunash
  • 6,973
  • 19
  • 64
  • 80
  • 1
    Maybe `xxd -r -p Check.txt > Check.tar` – cuonglm May 26 '15 at 09:13
  • its still text file , isnt work – maihabunash May 26 '15 at 09:17
  • What leads you to believe it's still a text file? `xxd -r -p` is the exact reverse of the `od` conversion you did; the output of [cuonglm](https://unix.stackexchange.com/users/38906/cuonglm)'s command should be strictly identical to the original tarball. – Stephen Kitt May 26 '15 at 09:24
  • xxd -r -p Check.txt > Check.tar ..... file Check.tar Check.tar: ascii text – maihabunash May 26 '15 at 09:26
  • I also try this - tar xvf Check.tar tar: directory checksum error – maihabunash May 26 '15 at 09:28
  • Answered [there](http://unix.stackexchange.com/a/65282) – Stéphane Chazelas May 26 '15 at 09:48
  • for me this test `echo hello world | od -t x1 | xxd -r -p` produces garbage. But `echo hello world | od -t x1 | xxd -r` works. – ctrl-alt-delor May 26 '15 at 11:09
  • @richard; for me both `od`/`xxd` versions create garbage (the latter creates spurious characters after the correctly decoded data). – Janis May 26 '15 at 11:38
  • @maihabunash; Note that it's not good to use different tools mixed for encoding and decoding. There were already answers suggesting `base64` and `uuencode`, and of course if you use `xxd` for **encoding** (instead of `od | cut`) then `xxd` will correctly work also for decoding. – Janis May 26 '15 at 11:42

3 Answers3

12
od -An -vtx1 Check.tar > Check.txt

You need -v or od will condense sequences of identical bytes.

For the reverse:

LC_ALL=C tr -cd 0-9a-fA-F < Check.txt | xxd -r -p > Check.tar

Or:

perl -ape '$_=pack "(H2)*", @F' Check.txt > Check.tar

If your purpose is to transfer files over a channel that only supports ASCII text, then there are dedicated tools for that like uuencode:

tar cf - myfiles.* | xz | uuencode myfiles.tar.xz | that-channel 

And to recover those files on the other end:

uudecode < file.uu

would recreate myfiles.tar.xz.

Or:

uudecode -o - < file.uu | xz -d | tar xf -

To extract the files.

Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
  • first thanx for the answer , but I need to create file.tar file , how to do it? – maihabunash May 26 '15 at 10:12
  • @maihabunash If you created file.txt without -v and with removing the address, then you can't reliably recover file.tar if there were condensed sequences (do a `grep '[*]' file.txt` to check) as you've lost the information of how long those condensed sequences were by removing the address. – Stéphane Chazelas May 26 '15 at 10:22
  • hi , my target is to compress more then 30 perl script with tar or zip or whatever then convert it to text and then convert it back to compressed file , is it possible? ( I see tar is problem but can we do it with other options ) – maihabunash May 26 '15 at 10:31
  • or maybe there are more option for example to compress the 30 scripts but as ascii or text mode , I need that because when I copy from one machine to another machine from unclear reason the binary files are changes ( chksum ) and not ascii files – maihabunash May 26 '15 at 10:33
  • 1
    @maihabunash, you're looking for uuencode or base64 encoding. Note that my answer covers your question. I give the code to convert back to binary from od output provided you don't forget the `-v` option. If you're transferring files over FTP, don't forget to set the mode to "binary" (`TYPE I` FTP command, something like `binary` in your client) – Stéphane Chazelas May 26 '15 at 10:50
  • if you tar ascii files the the tar file is also ascii. (tar only adds ascii, and does not distort or compress the original files.) – ctrl-alt-delor May 26 '15 at 11:15
  • @richard, tar will add NUL characters which make them non-text. In any case, I suspect the mangling in transfer problem is with characters like LF/CR, more than with bytes with the 8th bit set (all of which are taken care of by using uuencode). – Stéphane Chazelas May 26 '15 at 11:22
  • Upvote +1 for you thx – maihabunash May 26 '15 at 11:34
  • Re: `od -An -vtx1`: is it possible to avoid whitespaces? – pmor May 26 '23 at 15:09
  • @pmor, pipe to `tr -d '[:space:]'` if you don't want whitespace. Or use `xxd -p`. – Stéphane Chazelas May 26 '23 at 15:23
  • Oups, I've meant spaces, not whitespaces (so `tr -d ' '`). Now: how to feed the space-free output back to perl (or whatever) to reconstruct the `Check.tar`? – pmor May 26 '23 at 15:44
  • 1
    @pmor, It looks like you want the output of `xxd -p` which can be decoded with `xxd -r -p`. the `tr | xxd -r -p` approach already removes all whitepace (anything but xdigits). `perl -pe 'chomp;$_=pack"H*",$_'` to decode the output of `xxd -p` – Stéphane Chazelas May 26 '23 at 16:24
5

Answering the X part of this XY problem, I would recommend you investigate the reason your binary file transfers don't transfer properly.

If it turns out the reason is because you don't have an 8-bit clean datapath you could then use existing tools that were created to handle this situation, such as base64 or even uuencode. Old but still very effective.

tar czvf - /etc/h* | base64 >/tmp/tar.tgz.b64
ls -l /tmp/tar.tgz.b64
-rw-r--r-- 1 root root 7364 May 26 11:52 /tmp/tar.tgz.b64
...
base64 -d /tmp/tar.tgz.b64 | tar tzvf -

or

tar czvf - /etc/h* | uuencode - >/tmp/tar.tgz.uue
ls -l /tmp/tar.tgz.uue
-rw-r--r-- 1 root root 7530 May 26 11:51 /tmp/tar.tgz.uue
...
uudecode /tmp/tar.tgz.uue | tar xzvf -
roaima
  • 107,089
  • 14
  • 139
  • 261
3

In my case I didn't have xxd or uudecode on the remote device but I did have bash. I ended up with the following:

Convert from binary to txt with:

od -An -vtx1 myfile.bin > myfile.txt

Then convert back from txt to binary with:

while read p; do
    IFS=' ' read -r -a array <<< "$p" 
    for index in "${!array[@]}" 
    do
        echo -en "\x${array[index]}" 
    done
done < myfile.txt > myfile.bin
Jeremy
  • 31
  • 1