uuencode在大多数Linux发行版中需要单独安装:
sudo apt install sharutilssudo yum install sharutilssudo dnf install sharutilssudo pacman -S sharutilssudo zypper install sharutilsuuencode [选项] [输入文件] 输出文件名
| 参数 | 说明 |
|---|---|
| -m | 使用Base64编码(而非传统uuencode) |
| -o 输出文件 | 将编码输出到指定文件(而非标准输出) |
| -p | 编码到标准输出,并在最后显示编码统计 |
| -v, --version | 显示版本信息 |
| --help | 显示帮助信息 |
| 输入文件 | 要编码的文件(默认为标准输入) |
| 输出文件名 | 编码文件中指定的输出文件名(必需) |
# 将二进制文件编码为文本
uuencode image.jpg image.jpg > image.uue
# 查看编码结果
head -5 image.uue
# 输出示例:
# begin 644 image.jpg
# M_]C_X``02D9)1@`!`@`"`0`4`!`0`%`!`0`#`0`0`"`0`0`!`0`$`!`0`#`!`8
# M`"`!`0`"`!`0`"`!`0`"`!`0`"`!`0`"`!`0`"`!`0`"`!`0`"`!`0`"`!`0
# M`"`!`0`"`!`0`"`!`0`"`!`0`"`!`0`"`!`0`"`!`0`"`!`0`"`!`0`"`!`0
# `
# 编码并直接输出到文件
uuencode -o image.uue image.jpg image.jpg
# 从标准输入读取并编码
cat binary.dat | uuencode binary.dat > binary.uue
# 编码文本文件
uuencode document.txt document.txt > doc.uue
# 编码时指定不同的输出文件名
uuencode source.pdf download.pdf > encoded.uue
# 解码时会生成download.pdf而非source.pdf
# 使用Base64编码(-m参数)
uuencode -m image.jpg image.jpg > image.b64
# 查看Base64编码结果
head -3 image.b64
# 输出示例:
# begin-base64 644 image.jpg
# /9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0a
# HBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIy
# Base64编码到标准输出
uuencode -m -p archive.tar.gz archive.tar.gz
# 比较uuencode和Base64编码大小
ls -lh image.*
# 输出:
# -rw-r--r-- 1 user user 100K Jan 10 10:00 image.jpg
# -rw-r--r-- 1 user user 134K Jan 10 10:00 image.b64
# -rw-r--r-- 1 user user 134K Jan 10 10:00 image.uue
# Base64和uuencode编码大小相近,都比原文件大约33%
# 使用纯粹的Base64命令
base64 image.jpg > image.base64
# 注意:纯粹的base64输出不包含uuencode格式的头尾标记
# 解码uuencode文件
uudecode image.uue
# 生成image.jpg文件
# 解码Base64编码的文件
uudecode image.b64
# 生成image.jpg文件
# 解码到指定文件
uudecode -o output.jpg image.uue
# 解码标准输入
cat encoded.uue | uudecode
# 解码并显示详细信息
uudecode -v image.uue
# 输出:image.uue: decoded image.jpg (102400 bytes)
# 只测试不解码
uudecode -t image.uue
# 检查文件完整性但不解码
# 解码时保持原始权限
# uuencode编码中包含文件权限,uudecode会自动恢复
uuencode -m script.sh script.sh > script.b64
uudecode script.b64
ls -l script.sh
# 输出:-rwxr-xr-x 1 user user ... script.sh
# 查看原始文件权限
ls -l script.sh
# 输出:-rwxr-xr-x 1 user user 1024 Jan 10 10:00 script.sh
# 编码文件(包含权限信息)
uuencode script.sh script.sh > script.uue
head -1 script.uue
# 输出:begin 755 script.sh
# 755是八进制权限表示(rwxr-xr-x)
# 解码后会恢复权限
uudecode script.uue
ls -l script.sh
# 输出:-rwxr-xr-x 1 user user 1024 Jan 10 10:00 script.sh
# 编码不同权限的文件
chmod 644 document.txt
uuencode document.txt document.txt > doc.uue
head -1 doc.uue
# 输出:begin 644 document.txt
# 编码设备文件等特殊文件
# 注意:普通用户可能无权限读取设备文件
sudo uuencode /dev/null null.dev > null.uue
head -1 null.uue
# 输出:begin 666 /dev/null
# 方法1:分别编码每个文件
for file in *.jpg; do
uuencode "$file" "$file" > "${file}.uue"
done
# 方法2:使用tar打包后编码
tar -cf archive.tar *.jpg
uuencode archive.tar archive.tar > archive.uue
# 方法3:使用shar创建自解压文档
# shar工具可以创建包含多个文件的自解压shell脚本
shar *.jpg > images.shar
# 恢复时执行:sh images.shar
# 方法4:分别编码后合并
uuencode file1.txt file1.txt > files.uue
uuencode file2.txt file2.txt >> files.uue
uuencode file3.txt file3.txt >> files.uue
# 注意:这样合并的文件需要分别解码
# 解码多个文件
# 如果多个文件编码在一个文件中,uudecode会依次解码
uudecode files.uue
# 生成file1.txt, file2.txt, file3.txt
# 场景1:通过电子邮件发送附件
# 编码附件
uuencode -m report.pdf report.pdf > report.b64
# 将report.b64内容粘贴到邮件正文
# 接收方保存为.report.b64并运行:
uudecode report.b64
# 场景2:在论坛或聊天中分享文件
# 将二进制文件转换为文本,可直接粘贴
uuencode small_image.png small_image.png | head -20
# 复制输出的文本,接收方保存为.uue文件后解码
# 场景3:配置文件中的二进制数据
# 将小图标编码后嵌入配置文件
echo "# Icon data (uuencoded)" > config.ini
uuencode icon.ico icon.ico >> config.ini
echo "# End of icon data" >> config.ini
# 场景4:通过串口传输文件
# 编码文件
uuencode firmware.bin firmware.bin > firmware.uue
# 通过串口发送
cat firmware.uue > /dev/ttyS0
# 接收方从串口读取并解码
cat /dev/ttyS0 | uudecode
# 场景5:备份脚本中的二进制数据
#!/bin/bash
# 备份脚本,包含二进制数据
echo "Backup created: $(date)"
uuencode -m /etc/passwd passwd.backup
uuencode -m /etc/shadow shadow.backup
echo "Backup complete"
# 检查uuencode文件格式
file image.uue
# 输出:image.uue: ASCII uuencoded text
# 检查Base64文件格式
file image.b64
# 输出:image.b64: ASCII text, with very long lines
# 查看编码文件头部信息
head -2 image.uue
# 输出:
# begin 644 image.jpg
# M_]C_X``02D9)1@`!`@`"`0`4`!`0`%`!`0`#`0`0`"`0`0`!`0`$`!`0`#`!`8
# 查看编码文件尾部信息
tail -2 image.uue
# 输出:
# `
# end
# 统计编码文件行数
wc -l image.uue
# 输出:451 image.uue
# 计算编码膨胀率
original_size=$(stat -c%s image.jpg)
encoded_size=$(stat -c%s image.uue)
ratio=$(echo "scale=2; $encoded_size * 100 / $original_size" | bc)
echo "原始大小: ${original_size}字节"
echo "编码大小: ${encoded_size}字节"
echo "膨胀率: ${ratio}%"
# 验证编码完整性
uuencode -t image.uue 2>/dev/null && echo "编码完整" || echo "编码损坏"
# uuencode算法:
# 1. 每3字节(24位)二进制数据分为4个6位组
# 2. 每个6位组值(0-63)加上32,变成可打印ASCII字符(32-95)
# 3. 空白字符(ASCII 32,即空格)用'`'字符(ASCII 96)表示
# 4. 每行编码45字节原始数据(60字符编码文本)
# 示例:编码三个字节 0x12 0x34 0x56
# 二进制:00010010 00110100 01010110
# 分为4个6位组:
# 000100 100011 010001 010110
# 十进制:4 35 17 22
# 加32:36 67 49 54
# ASCII字符:$ C 1 6
# 所以0x12 0x34 0x56编码为 "$C16"
# Base64算法(uuencode -m使用):
# 1. 每3字节(24位)分为4个6位组
# 2. 每个6位组映射到64字符表:A-Z a-z 0-9 + /
# 3. 每行76字符(规范建议)
# 查看编码表
echo "=== uuencode编码表 ==="
echo "值 字符 值 字符 值 字符 值 字符"
for ((i=0; i<16; i++)); do
for ((j=0; j<4; j++)); do
n=$((i + j*16))
if [ $n -lt 64 ]; then
c=$((n + 32))
# 空格特殊处理
if [ $c -eq 32 ]; then
c=96 # 空格用'`'表示
fi
printf "%2d \\x$(printf %x $c) " $n
fi
done
echo
done
| 工具 | 格式 | 膨胀率 | 标准化 | 现代使用 | 特点 |
|---|---|---|---|---|---|
| uuencode | 传统uu编码 | ~33% | POSIX | 遗留系统 | Unix传统,包含权限 |
| Base64 | RFC 4648 | ~33% | IETF标准 | 广泛 | Web标准,通用 |
| xxd | 十六进制 | ~200% | 工具特定 | 调试用 | 可读性好,用于调试 |
| od | 八进制/十六进制 | 高 | POSIX | 调试用 | 多种格式,可读性 |
| openssl base64 | Base64 | ~33% | 标准 | 安全应用 | OpenSSL实现,安全 |
| gzip+base64 | 压缩+编码 | 可小于0% | 组合 | 高效传输 | 先压缩再编码,高效 |
# uuencode(传统)
uuencode file.bin file.bin > file.uue
# Base64(现代标准)
base64 file.bin > file.b64
# 或
uuencode -m file.bin file.bin > file.b64
# xxd(十六进制,用于调试)
xxd file.bin | head -5
# 输出:
# 00000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452 .PNG........IHDR
# 00000010: 0000 02d0 0000 0240 0802 0000 00c5 1c4c .......@.......L
# od(八进制/十六进制转储)
od -x file.bin | head -5
# openssl base64
openssl base64 -in file.bin -out file.b64
openssl base64 -d -in file.b64 -out file.decoded
# gzip压缩后base64编码(高效传输)
gzip -c file.bin | base64 > file.bin.gz.b64
# 解码
base64 -d file.bin.gz.b64 | gzip -d > file.restored.bin
# 比较不同编码的大小
ls -lh file.*
# 输出示例:
# -rw-r--r-- 1 user user 100K file.bin # 原始
# -rw-r--r-- 1 user user 134K file.b64 # Base64
# -rw-r--r-- 1 user user 134K file.uue # uuencode
# -rw-r--r-- 1 user user 201K file.hex # xxd十六进制
# -rw-r--r-- 1 user user 45K file.bin.gz.b64 # 压缩+编码
#!/bin/bash
# 批量文件编码转换工具
SOURCE_DIR="$1"
OUTPUT_DIR="$2"
ENCODING="base64" # 或 "uuencode"
ACTION="encode" # 或 "decode"
# 默认值
if [ -z "$SOURCE_DIR" ]; then
SOURCE_DIR="."
fi
if [ -z "$OUTPUT_DIR" ]; then
OUTPUT_DIR="encoded_files"
fi
echo "=== 批量文件编码转换工具 ==="
echo "源目录: $SOURCE_DIR"
echo "输出目录: $OUTPUT_DIR"
echo "编码类型: $ENCODING"
echo "操作: $ACTION"
echo "开始时间: $(date)"
echo ""
# 创建输出目录
mkdir -p "$OUTPUT_DIR"
# 检查命令是否存在
check_command() {
if ! command -v "$1" >/dev/null 2>&1; then
echo "错误: 命令未找到 - $1"
return 1
fi
return 0
}
# 编码函数
encode_file() {
local src_file="$1"
local dst_file="$2"
if [ "$ENCODING" = "base64" ]; then
uuencode -m "$src_file" "$(basename "$src_file")" > "$dst_file"
elif [ "$ENCODING" = "uuencode" ]; then
uuencode "$src_file" "$(basename "$src_file")" > "$dst_file"
else
echo "错误: 不支持的编码类型: $ENCODING"
return 1
fi
}
# 解码函数
decode_file() {
local src_file="$1"
local dst_dir="$2"
cd "$dst_dir"
if uudecode "$src_file"; then
echo "✓ 解码成功"
else
echo "✗ 解码失败"
return 1
fi
cd - >/dev/null
}
# 处理单个文件
process_file() {
local file="$1"
local filename=$(basename "$file")
local extension=""
if [ "$ENCODING" = "base64" ]; then
extension=".b64"
elif [ "$ENCODING" = "uuencode" ]; then
extension=".uue"
fi
echo "处理: $filename"
if [ "$ACTION" = "encode" ]; then
# 编码
local output_file="$OUTPUT_DIR/${filename}${extension}"
echo -n " 编码..."
if encode_file "$file" "$output_file"; then
# 计算大小和膨胀率
original_size=$(stat -c%s "$file" 2>/dev/null || echo 0)
encoded_size=$(stat -c%s "$output_file" 2>/dev/null || echo 0)
if [ "$original_size" -gt 0 ]; then
ratio=$(echo "scale=1; $encoded_size * 100 / $original_size" | bc 2>/dev/null || echo 0)
echo "✓ 完成 (${original_size} → ${encoded_size} 字节, 膨胀: ${ratio}%)"
else
echo "✓ 完成"
fi
else
echo "✗ 失败"
fi
elif [ "$ACTION" = "decode" ]; then
# 解码
echo -n " 解码..."
if decode_file "$file" "$OUTPUT_DIR"; then
echo "✓ 完成"
else
echo "✗ 失败"
fi
fi
}
# 主处理循环
processed=0
success=0
failed=0
if [ "$ACTION" = "encode" ]; then
# 查找常规文件进行编码
find "$SOURCE_DIR" -maxdepth 1 -type f ! -name ".*" | while read file; do
processed=$((processed + 1))
if process_file "$file"; then
success=$((success + 1))
else
failed=$((failed + 1))
fi
echo ""
done
elif [ "$ACTION" = "decode" ]; then
# 查找编码文件进行解码
find "$SOURCE_DIR" -maxdepth 1 -type f \( -name "*.uue" -o -name "*.b64" \) | while read file; do
processed=$((processed + 1))
if process_file "$file"; then
success=$((success + 1))
else
failed=$((failed + 1))
fi
echo ""
done
fi
# 显示统计信息
echo "=== 处理完成 ==="
echo "总处理文件: $processed"
echo "成功: $success"
echo "失败: $failed"
echo "输出目录: $OUTPUT_DIR"
echo ""
# 显示输出目录内容
if [ "$processed" -gt 0 ]; then
echo "输出目录内容:"
ls -lh "$OUTPUT_DIR" | head -20
fi
#!/bin/bash
# 电子邮件附件编码/解码工具
VERSION="1.0"
AUTHOR="System Tool"
DEFAULT_ENCODING="base64"
show_menu() {
clear
echo "╔══════════════════════════════════════════════╗"
echo "║ 电子邮件附件工具 v$VERSION ║"
echo "╚══════════════════════════════════════════════╝"
echo ""
echo "1. 编码文件为电子邮件正文"
echo "2. 从电子邮件正文解码文件"
echo "3. 编码多个文件"
echo "4. 解码多个文件"
echo "5. 查看编码文件信息"
echo "6. 测试编码/解码完整性"
echo "7. 设置默认编码 (当前: $DEFAULT_ENCODING)"
echo "8. 退出"
echo ""
echo -n "请选择操作 [1-8]: "
}
encode_for_email() {
echo -n "请输入要编码的文件路径: "
read filepath
if [ ! -f "$filepath" ]; then
echo "错误: 文件不存在"
read -p "按回车键继续..."
return
fi
echo -n "使用Base64编码? [Y/n]: "
read use_base64
if [[ "$use_base64" =~ ^[Nn]$ ]]; then
encoding="uuencode"
else
encoding="base64"
fi
echo -n "输出到文件? (留空显示在屏幕): "
read output_file
echo ""
echo "=== 编码结果 ==="
echo ""
if [ -n "$output_file" ]; then
echo "保存到: $output_file"
echo "=== 开始编码 ===" > "$output_file"
echo "" >> "$output_file"
if [ "$encoding" = "base64" ]; then
uuencode -m "$filepath" "$(basename "$filepath")" >> "$output_file"
else
uuencode "$filepath" "$(basename "$filepath")" >> "$output_file"
fi
echo "" >> "$output_file"
echo "=== 编码结束 ===" >> "$output_file"
echo "文件已保存。使用方法:"
echo "1. 将 $output_file 内容复制到电子邮件正文"
echo "2. 接收方保存邮件正文为 .uue 或 .b64 文件"
echo "3. 运行: uudecode 文件名"
else
echo "复制以下内容到电子邮件正文:"
echo ""
echo "=== 开始复制 === (共3行分隔线)"
echo ""
if [ "$encoding" = "base64" ]; then
uuencode -m "$filepath" "$(basename "$filepath")"
else
uuencode "$filepath" "$(basename "$filepath")"
fi
echo ""
echo "=== 结束复制 ==="
echo ""
echo "接收方使用方法:"
echo "1. 保存邮件正文为 attachment.uue"
echo "2. 运行: uudecode attachment.uue"
fi
read -p "按回车键继续..."
}
decode_from_email() {
echo "请选择解码方式:"
echo "1. 从文件解码"
echo "2. 粘贴内容解码"
echo -n "选择 [1-2]: "
read method
if [ "$method" = "1" ]; then
echo -n "输入编码文件路径: "
read encoded_file
if [ ! -f "$encoded_file" ]; then
echo "错误: 文件不存在"
read -p "按回车键继续..."
return
fi
echo -n "输出目录 (留空为当前目录): "
read output_dir
if [ -n "$output_dir" ]; then
mkdir -p "$output_dir"
cd "$output_dir"
fi
echo "开始解码..."
if uudecode "$encoded_file"; then
echo "✓ 解码成功"
echo "生成的文件:"
ls -l | grep -v "$encoded_file" | head -5
else
echo "✗ 解码失败"
fi
if [ -n "$output_dir" ]; then
cd - >/dev/null
fi
elif [ "$method" = "2" ]; then
echo "请粘贴编码内容 (以空行结束):"
echo ""
# 创建临时文件
temp_file=$(mktemp)
# 读取多行输入,直到空行
echo "粘贴内容 (输入空行结束):"
while IFS= read -r line; do
if [ -z "$line" ]; then
break
fi
echo "$line" >> "$temp_file"
done
echo -n "输出目录 (留空为当前目录): "
read output_dir
if [ -n "$output_dir" ]; then
mkdir -p "$output_dir"
cd "$output_dir"
fi
echo "开始解码..."
if uudecode "$temp_file"; then
echo "✓ 解码成功"
echo "生成的文件:"
ls -l | head -5
else
echo "✗ 解码失败"
fi
# 清理
rm -f "$temp_file"
if [ -n "$output_dir" ]; then
cd - >/dev/null
fi
fi
read -p "按回车键继续..."
}
# 主循环
while true; do
show_menu
read choice
case $choice in
1) encode_for_email ;;
2) decode_from_email ;;
3)
echo "批量编码功能开发中..."
read -p "按回车键继续..."
;;
4)
echo "批量解码功能开发中..."
read -p "按回车键继续..."
;;
5)
echo -n "输入编码文件路径: "
read info_file
if [ -f "$info_file" ]; then
echo "文件信息:"
file "$info_file"
echo ""
echo "前5行内容:"
head -5 "$info_file"
fi
read -p "按回车键继续..."
;;
6)
echo "编码测试功能开发中..."
read -p "按回车键继续..."
;;
7)
echo -n "选择默认编码 (base64/uuencode): "
read new_encoding
if [ "$new_encoding" = "base64" ] || [ "$new_encoding" = "uuencode" ]; then
DEFAULT_ENCODING="$new_encoding"
echo "默认编码已设置为: $DEFAULT_ENCODING"
else
echo "无效的编码类型"
fi
read -p "按回车键继续..."
;;
8)
echo "再见!"
exit 0
;;
*)
echo "无效选择"
read -p "按回车键继续..."
;;
esac
done
#!/bin/bash
# 这是一个bash包装器,调用Python实现更强大的编解码功能
PYTHON_SCRIPT=$(cat << 'EOF'
#!/usr/bin/env python3
"""
uuencode/Base64 编解码工具库
支持多种编码格式和高级功能
"""
import os
import sys
import base64
import binascii
import argparse
from pathlib import Path
from typing import Optional, Tuple
class UUEncoder:
"""uuencode/Base64 编码解码器"""
@staticmethod
def uuencode(data: bytes, filename: str = "data", mode: int = 0o644) -> str:
"""
将二进制数据编码为uuencode格式
Args:
data: 二进制数据
filename: 输出文件名
mode: 文件权限(八进制)
Returns:
uuencode编码的字符串
"""
# uuencode头部
header = f"begin {mode:o} {filename}\n"
# uuencode编码
encoded_lines = []
for i in range(0, len(data), 45):
chunk = data[i:i+45]
# 每行第一个字符是长度字节(ASCII 32 + 长度)
line_len = len(chunk)
if line_len == 0:
break
encoded_lines.append(chr(line_len + 32))
# 编码3字节为一组
for j in range(0, len(chunk), 3):
group = chunk[j:j+3]
# 补齐到3字节
while len(group) < 3:
group += b'\x00'
# 3字节 = 24位,分为4个6位组
value = (group[0] << 16) | (group[1] << 8) | group[2]
for k in range(4):
six_bits = (value >> (18 - k*6)) & 0x3F
# 6位值加32变成可打印ASCII
char_code = six_bits + 32
if char_code == 32: # 空格特殊处理
char_code = 96 # 反引号
encoded_lines.append(chr(char_code))
encoded_lines.append('\n')
# 结束标记
encoded_lines.append('`\n')
encoded_lines.append('end\n')
return header + ''.join(encoded_lines)
@staticmethod
def uudecode(encoded_data: str) -> Tuple[Optional[bytes], Optional[str], Optional[int]]:
"""
解码uuencode数据
Args:
encoded_data: uuencode编码的字符串
Returns:
(二进制数据, 文件名, 权限模式) 或 (None, None, None) 如果失败
"""
lines = encoded_data.strip().split('\n')
if not lines or not lines[0].startswith('begin '):
return None, None, None
# 解析头部
header_parts = lines[0].split()
if len(header_parts) < 3:
return None, None, None
try:
mode = int(header_parts[1], 8) # 八进制解析
filename = header_parts[2]
except ValueError:
return None, None, None
# 解码数据
decoded = bytearray()
for line in lines[1:]:
if line == 'end':
break
if not line or line == '`':
continue
# 第一个字符是长度
line_len = ord(line[0]) - 32
if line_len <= 0:
continue
# 解码数据
data_chars = line[1:]
for i in range(0, len(data_chars), 4):
chunk = data_chars[i:i+4]
if len(chunk) < 4:
break
# 4个字符恢复为3字节
value = 0
for j, char in enumerate(chunk):
char_code = ord(char)
if char_code == 96: # 反引号转空格
char_code = 32
six_bits = char_code - 32
value = (value << 6) | six_bits
# 提取3字节
bytes_decoded = [
(value >> 16) & 0xFF,
(value >> 8) & 0xFF,
value & 0xFF
]
# 添加到结果,根据实际长度截断
bytes_to_add = min(3, line_len - len(decoded))
decoded.extend(bytes_decoded[:bytes_to_add])
return bytes(decoded), filename, mode
@staticmethod
def base64_encode(data: bytes, filename: str = "data", mode: int = 0o644) -> str:
"""
将二进制数据编码为Base64格式(uuencode风格)
Args:
data: 二进制数据
filename: 输出文件名
mode: 文件权限
Returns:
Base64编码的字符串
"""
# Base64头部
header = f"begin-base64 {mode:o} {filename}\n"
# Base64编码
encoded = base64.b64encode(data).decode('ascii')
# 每行76字符(符合RFC)
encoded_lines = []
for i in range(0, len(encoded), 76):
encoded_lines.append(encoded[i:i+76])
# 结束标记
encoded_lines.append('')
encoded_lines.append('===')
encoded_lines.append('')
return header + '\n'.join(encoded_lines)
@staticmethod
def base64_decode(encoded_data: str) -> Tuple[Optional[bytes], Optional[str], Optional[int]]:
"""
解码Base64数据(uuencode风格)
Args:
encoded_data: Base64编码的字符串
Returns:
(二进制数据, 文件名, 权限模式) 或 (None, None, None) 如果失败
"""
lines = encoded_data.strip().split('\n')
if not lines or not lines[0].startswith('begin-base64 '):
return None, None, None
# 解析头部
header_parts = lines[0].split()
if len(header_parts) < 3:
return None, None, None
try:
mode = int(header_parts[1], 8)
filename = header_parts[2]
except ValueError:
return None, None, None
# 提取Base64数据
base64_data = []
in_data = False
for line in lines[1:]:
if line.startswith('===') or line.startswith('end'):
break
if line and not line.isspace():
base64_data.append(line)
# 解码
try:
decoded = base64.b64decode(''.join(base64_data))
return decoded, filename, mode
except (binascii.Error, ValueError):
return None, None, None
def main():
parser = argparse.ArgumentParser(description='uuencode/Base64 编解码工具')
parser.add_argument('action', choices=['encode', 'decode', 'info'],
help='操作: encode=编码, decode=解码, info=信息')
parser.add_argument('-i', '--input', help='输入文件')
parser.add_argument('-o', '--output', help='输出文件')
parser.add_argument('-t', '--type', choices=['uuencode', 'base64'], default='base64',
help='编码类型 (默认: base64)')
parser.add_argument('-f', '--filename', help='输出文件名')
parser.add_argument('-m', '--mode', type=lambda x: int(x, 8), default=0o644,
help='文件权限 (八进制, 默认: 644)')
args = parser.parse_args()
encoder = UUEncoder()
if args.action == 'encode':
# 读取输入文件
if args.input:
with open(args.input, 'rb') as f:
data = f.read()
default_filename = args.input
else:
data = sys.stdin.buffer.read()
default_filename = 'data'
# 编码
if args.type == 'uuencode':
encoded = encoder.uuencode(data, args.filename or default_filename, args.mode)
else: # base64
encoded = encoder.base64_encode(data, args.filename or default_filename, args.mode)
# 输出
if args.output:
with open(args.output, 'w') as f:
f.write(encoded)
else:
sys.stdout.write(encoded)
elif args.action == 'decode':
# 读取编码数据
if args.input:
with open(args.input, 'r') as f:
encoded_data = f.read()
else:
encoded_data = sys.stdin.read()
# 自动检测编码类型
if encoded_data.startswith('begin-base64 '):
data, filename, mode = encoder.base64_decode(encoded_data)
elif encoded_data.startswith('begin '):
data, filename, mode = encoder.uuencode_decode(encoded_data)
else:
# 尝试Base64解码
try:
data = base64.b64decode(encoded_data)
filename = args.filename or 'decoded.bin'
mode = args.mode
except binascii.Error:
print("错误: 无法识别的编码格式", file=sys.stderr)
sys.exit(1)
if data is None:
print("错误: 解码失败", file=sys.stderr)
sys.exit(1)
# 输出
output_file = args.output or filename
with open(output_file, 'wb') as f:
f.write(data)
# 设置权限
if mode is not None:
try:
os.chmod(output_file, mode)
except OSError:
pass
print(f"解码成功: {output_file} (权限: {oct(mode)[2:] if mode else '默认'})")
elif args.action == 'info':
if args.input:
with open(args.input, 'r') as f:
encoded_data = f.read()
else:
encoded_data = sys.stdin.read()
if encoded_data.startswith('begin-base64 '):
print("格式: Base64 (uuencode风格)")
header = encoded_data.split('\n')[0]
parts = header.split()
if len(parts) >= 3:
print(f"文件名: {parts[2]}")
print(f"权限: {parts[1]}")
elif encoded_data.startswith('begin '):
print("格式: uuencode")
header = encoded_data.split('\n')[0]
parts = header.split()
if len(parts) >= 3:
print(f"文件名: {parts[2]}")
print(f"权限: {parts[1]}")
else:
print("格式: 未知或原始Base64")
# 估计原始大小
lines = encoded_data.strip().split('\n')
data_lines = [l for l in lines if l and not l.startswith('begin') and not l.startswith('end') and l != '`' and not l.startswith('===')]
if data_lines:
print(f"数据行数: {len(data_lines)}")
# 粗略估计
if encoded_data.startswith('begin '):
# uuencode: 每行约45字节原始数据
estimated = len(data_lines) * 45
else:
# Base64: 每4字符对应3字节
total_chars = sum(len(l) for l in data_lines)
estimated = total_chars * 3 // 4
print(f"估计原始大小: {estimated} 字节")
if __name__ == '__main__':
main()
EOF
)
# 检查Python是否可用
if command -v python3 >/dev/null 2>&1; then
# 执行Python脚本
python3 -c "$PYTHON_SCRIPT" "$@"
else
echo "错误: 需要Python 3来运行此工具"
echo "请安装Python 3或使用系统自带的uuencode/uudecode命令"
exit 1
fi
| 对比项 | uuencode | Base64 |
|---|---|---|
| 历史 | Unix传统(1980年代) | MIME标准(1990年代) |
| 标准 | POSIX标准 | RFC 4648(IETF) |
| 字符集 | 32-95的ASCII字符 | A-Z a-z 0-9 + / |
| 行格式 | 每行60字符,首字符为长度 | 每行76字符建议 |
| 头部 | begin 权限 文件名 | begin-base64 权限 文件名 |
| 空白处理 | 空格(32)用`(96)表示 | 无特殊处理 |
| 现代使用 | 遗留系统 | Web标准 |
# 兼容性要求高时使用uuencode
uuencode file.bin file.bin > file.uue
# 现代应用使用Base64
base64 file.bin > file.b64
# 或
uuencode -m file.bin file.bin > file.b64
# Web应用使用标准Base64
# 注意:uuencode -m生成的Base64包含头部,而纯base64命令不包含
# 电子邮件附件通常需要头部信息
# 转换uuencode为Base64
uudecode file.uue
uuencode -m decoded.bin decoded.bin > file.b64
sharutils包中:
sudo apt update && sudo apt install sharutilssudo yum install sharutilssudo dnf install sharutilssudo pacman -S sharutilssudo zypper install sharutils# 检查是否安装成功
which uuencode
which uudecode
# 查看版本
uuencode --version
uudecode --version
# 测试基本功能
echo "test" > test.txt
uuencode test.txt test.txt > test.uue
uudecode test.uue
cat test.txt
# 输出:test
# 如果没有包管理器,从源码编译
wget https://ftp.gnu.org/gnu/sharutils/sharutils-4.15.2.tar.xz
tar -xf sharutils-4.15.2.tar.xz
cd sharutils-4.15.2
./configure
make
sudo make install
# 替代方案:使用其他Base64工具
# 大多数系统有base64命令
base64 --version
# 或使用openssl
openssl base64 -in file -out file.b64
openssl base64 -d -in file.b64 -out file
# 使用Python(大多数系统已安装)
python3 -m base64 -e file.bin > file.b64
python3 -m base64 -d file.b64 > file.decoded
# 使用Perl
perl -MMIME::Base64 -e 'print encode_base64(join("", <>))' < file.bin > file.b64
perl -MMIME::Base64 -e 'print decode_base64(join("", <>))' < file.b64 > file.decoded
# 1. 检查文件格式
file encoded.uue
# 应该显示:ASCII uuencoded text 或类似
# 2. 检查文件头部
head -1 encoded.uue
# 应该以 "begin" 或 "begin-base64" 开头
# 3. 检查文件尾部
tail -2 encoded.uue
# 应该以 "end" 或 "`" 和 "end" 结尾
# 4. 修复行结束符(如果来自Windows)
dos2unix encoded.uue
# 或
tr -d '\r' < encoded.uue > encoded_fixed.uue
# 5. 尝试不同的解码工具
# 使用uuencode
uudecode encoded.uue
# 使用base64
base64 -d encoded.uue > decoded.bin
# 使用openssl
openssl base64 -d -in encoded.uue -out decoded.bin
# 6. 手动修复常见问题
# 删除非ASCII字符
tr -cd '\11\12\15\40-\176' < encoded.uue > cleaned.uue
# 修复可能的空格问题
sed 's/ /`/g' encoded.uue > fixed.uue
# 7. 分步解码
# 提取Base64数据(如果是Base64编码)
sed -n '/^begin-base64/,/^===/p' encoded.uue | sed '1d;$d' > data.b64
base64 -d data.b64 > decoded.bin
# 8. 使用Python进行灵活解码
python3 -c "
import base64, sys
with open('encoded.uue', 'r') as f:
data = f.read()
if data.startswith('begin-base64'):
lines = [l for l in data.split('\n')
if l and not l.startswith('begin') and not l.startswith('===')]
data = ''.join(lines)
try:
decoded = base64.b64decode(data)
with open('decoded.bin', 'wb') as f:
f.write(decoded)
print('解码成功')
except:
print('Base64解码失败')
elif data.startswith('begin '):
print('尝试使用系统uudecode')
import subprocess
subprocess.run(['uudecode', 'encoded.uue'])
else:
print('无法识别的格式')
"
# 9. 验证编码完整性
# 重新编码解码后的文件,比较是否一致
uudecode encoded.uue
uuencode decoded.bin decoded.bin > reencoded.uue
diff encoded.uue reencoded.uue
# 如果没有输出,说明编码一致
# 10. 如果所有方法都失败,尝试从编码中提取文本
strings encoded.uue | head -20
# 或尝试修复为纯Base64
grep -v '^begin' encoded.uue | grep -v '^end' | tr -d '\n' | base64 -d > recovered.bin
解码uuencode文件:
uudecode file.uue
uudecode -o output.bin file.uue
uudecode -t file.uue
cat file.uue | uudecode
Base64编码解码:
base64 file.bin > file.b64
base64 -d file.b64 > file.bin
base64 -w 0 file.bin # 不换行
cat file.bin | base64
十六进制转储:
xxd file.bin
xxd -r hex.txt > file.bin
xxd -l 100 file.bin
xxd -p file.bin # 纯十六进制
创建自解压shell归档:
shar *.txt > archive.shar
sh archive.shar
shar -c *.txt # 创建压缩归档
unshar archive.shar