Wednesday, May 27, 2009

uuencode -> base64

If you have a modern version of Unix, you'll have a more recent version of the 'uuencode' command that can generate base64 output with the -m flag.

If you don't, you can convert uuencode output to base64 easily enough. You just have to remove the 'begin' and 'end' lines, strip off the 'count' character off the front of each line, and then convert the characters from the uuencode character set to the base64 one.

This is all relatively easy to do as a shell script pipeline. The hardest part is putting the special characters in the uuencode character set into a variable. But careful escaping can make it happen:


#! /bin/sh

# The uuencode character set
UU=' !"#$%&'"'"'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`'
# The base64 character set - note the extra ` -> A conversion
B6='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/A'

tail +2 | egrep -v ^end - | tr "$UU" "$B6" | sed -e "s/^.//g"


You will have to remove the line breaks stuck in there by blogger. Sorry.

This script also leaves out one step that makes the output potentially invalid base64 - if the number of characters in the output stream is not an even multiple of 4, then '=' characters are added to represent 0 padding. You can do that experimentally by hand if you absolutely need it, but having to count the number of characters (not including the newlines) as you output them would be rather painful. At that point, it makes more sense to just write base64 yourself in C.

1 comment:

Anonymous said...

Here's a modification to the script to get the padding right so that the output is valid base64.


#!/bin/sh
# The uuencode character set
UU=' !"#$%&'"'"'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`a'
# The base64 character set - note the extra ` -> A conversion (and a -> = )
B6='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/A='
sed -e'/^begin/d' -e'/^end/d' -e'/^$/d' -e'/^ $/d' | awk '{
numpad=(index(uu,substr($0,1,1))-1)%3;
if(numpad>0)numpad=3-numpad;
printf("%s", substr($0,2,(length($0)-1-numpad)));
if(numpad==0) printf("\n");
if(numpad==1) printf("a\n");
if(numpad==2) printf("aa\n");
}' uu="$UU" | tr "$UU" "$B6"