Linux bzip2命令

功能说明:bzip2命令用于使用Burrows-Wheeler算法压缩和解压缩文件,产生.bz2格式的压缩文件。它以高压缩率著称,特别适合压缩文本文件,是Linux系统中最常用的压缩工具之一。
主要功能
  • 压缩文件为.bz2格式
  • 解压.bz2压缩文件
  • 多种压缩级别选择(1-9)
  • 测试压缩文件完整性
  • 保留原始文件(可选)
  • 多文件批量处理
算法特点
  • 基于Burrows-Wheeler变换
  • 使用霍夫曼编码
  • 块大小为100-900KB
  • 压缩率高,但速度较慢
  • 适合文本文件和源代码
  • 开源且广泛使用

命令语法

语法格式
bzip2 [选项] [文件名...]

命令参数

参数 说明
-1 到 -9 设置压缩级别(1最快压缩,9最高压缩)
--fast 等同于-1,最快压缩
--best 等同于-9,最佳压缩(默认)
-d, --decompress 解压文件(同bunzip2)
-z, --compress 压缩文件(默认行为)
-k, --keep 压缩/解压后保留原始文件
-f, --force 强制覆盖已存在的输出文件
-t, --test 测试压缩文件的完整性
-c, --stdout 将结果输出到标准输出
-q, --quiet 静默模式,不显示警告信息
-v, --verbose 详细模式,显示处理信息
-s, --small 减少内存使用(适用于小内存系统)
-L, --license 显示软件许可证信息
-V, --version 显示版本信息
--help 显示帮助信息

压缩级别详解

级别 块大小 压缩速度 压缩率 内存使用 推荐场景
-1 (--fast) 100KB 最快 最低 最少 快速测试,临时文件
-2 200KB 快 较低 较少 日常压缩
-3 300KB 较快 中等 中等 一般用途
-4 400KB 中等 较好 中等 平衡模式
-5 500KB 较慢 好 较高 文档存档
-6 600KB 慢 很好 高 长期存储
-7 700KB 很慢 非常好 很高 重要数据
-8 800KB 极慢 极好 极高 关键数据
-9 (--best) 900KB 最慢 最佳 最多 终极压缩

使用示例

1. 基本压缩操作 常用
示例
# 压缩单个文件(默认删除原文件)
bzip2 file.txt
# 生成:file.txt.bz2,原文件被删除

# 压缩多个文件
bzip2 file1.txt file2.txt file3.txt

# 压缩并保留原文件
bzip2 -k document.pdf
# 生成:document.pdf.bz2,原文件保留

# 压缩整个目录(配合tar)
tar -cjf archive.tar.bz2 directory/

# 压缩到标准输出
bzip2 -c file.txt > compressed.bz2
2. 使用不同压缩级别
# 快速压缩(低压缩率)
bzip2 -1 largefile.log
# 或
bzip2 --fast data.csv

# 默认压缩(-9,最高压缩率)
bzip2 important_document.txt
# 等同于
bzip2 -9 confidential.pdf

# 平衡压缩(推荐日常使用)
bzip2 -4 regular_file.txt

# 测试不同级别的效果
for i in {1..9}; do
    echo "级别 $i:"
    time bzip2 -k -$i testfile.txt
    ls -lh testfile.txt.bz2
    rm testfile.txt.bz2
    echo "---"
done
3. 解压操作
# 解压单个文件
bzip2 -d file.txt.bz2
# 或
bunzip2 file.txt.bz2

# 解压并保留原压缩文件
bzip2 -dk archive.bz2

# 解压到标准输出
bzip2 -dc file.txt.bz2

# 解压多个文件
bzip2 -d file1.bz2 file2.bz2 file3.bz2

# 解压tar.bz2文件
tar -xjf archive.tar.bz2
4. 测试文件完整性
# 测试单个压缩文件
bzip2 -t archive.bz2
# 无输出表示文件完整

# 测试多个文件
bzip2 -t file1.bz2 file2.bz2 file3.bz2

# 详细测试模式
bzip2 -tv data.bz2
# 输出:data.bz2: ok

# 在脚本中测试
if bzip2 -t backup.bz2 2>/dev/null; then
    echo "压缩文件完整"
else
    echo "警告:压缩文件可能损坏"
fi
5. 查看压缩文件信息
# 查看压缩文件信息
bzip2 -lv file.bz2
# 输出示例:
# file.bz2: 1.234:1, 8.100 bits/byte, 19.05% saved, 1024000 in, 830000 out.

# 查看文件但不解压
bzcat file.bz2 | head -20
bzcat file.bz2 | wc -l

# 搜索压缩文件内容
bzcat logfile.bz2 | grep "error"
bzcat access.log.bz2 | grep "404"

# 比较压缩文件内容
diff <(bzcat file1.bz2) <(bzcat file2.bz2)
6. 批量处理文件
# 压缩当前目录下所有.txt文件
for file in *.txt; do
    bzip2 -k "$file"
done

# 解压当前目录下所有.bz2文件
for file in *.bz2; do
    bzip2 -dk "$file"
done

# 批量压缩并移动到备份目录
mkdir -p backup
for file in *.log; do
    bzip2 -c "$file" > "backup/${file}.bz2"
done

# 使用find批量压缩
find . -name "*.log" -exec bzip2 -k {} \;

# 使用xargs批量解压
find . -name "*.bz2" -print0 | xargs -0 bzip2 -d
7. 实际工作场景
# 场景1:日志文件压缩
# 压缩旧日志文件
find /var/log -name "*.log" -mtime +30 -exec bzip2 -9 {} \;

# 场景2:数据库备份压缩
mysqldump -u root -p database_name | bzip2 -9 > backup.sql.bz2

# 场景3:网站备份
tar -cjf website_backup_$(date +%Y%m%d).tar.bz2 /var/www/html

# 场景4:源码分发
cd project-1.0
tar -cjf ../project-1.0.tar.bz2 .

# 场景5:传输前压缩
bzip2 -9c large_file.iso | ssh user@server "cat > /backup/compressed.bz2"

压缩算法原理

Burrows-Wheeler压缩算法流程
输入数据
Burrows-Wheeler变换(BWT)
移动到前端编码(MTF)
游程编码(RLE)
霍夫曼编码
输出.bz2文件
算法各阶段说明
# 1. Burrows-Wheeler变换(BWT)
# 将重复字符聚集在一起,便于后续压缩
原始数据: "banana"
BWT变换: "annb$aa"

# 2. 移动到前端编码(MTF)
# 用出现位置编码字符
BWT数据: "annb$aa"
MTF编码: "011001" (示例)

# 3. 游程编码(RLE)
# 压缩重复序列
MTF数据: "00001111"
RLE编码: "4,0,4,1"

# 4. 霍夫曼编码
# 用变长编码压缩数据
RLE数据: "4,0,4,1"
霍夫曼编码: 二进制流

与其他压缩工具对比

工具 格式 压缩率 速度 内存 特点 推荐用途
bzip2 .bz2 高 中等 较高 文本压缩优秀,开源 软件分发,文档
gzip .gz 中等 快 低 速度快,通用性好 日志,网络传输
xz .xz 很高 慢 高 最高压缩率,LZMA2 归档,分发
zip .zip 中等 快 低 跨平台,广泛支持 Windows兼容
7z .7z 很高 中等 较高 高压缩率,多种算法 备份,存档
zstd .zst 可调 很快 中等 速度极快,可调压缩 实时压缩,打包
压缩性能测试示例
#!/bin/bash
# 压缩工具性能测试脚本

TEST_FILE="test_data.bin"
TEST_SIZE="100M"

echo "创建测试文件 ($TEST_SIZE)..."
dd if=/dev/urandom of="$TEST_FILE" bs=1M count=100 2>/dev/null

echo -e "\n=== 压缩性能测试 ==="
echo "工具      耗时(s)  压缩后大小  压缩率  内存峰值"

# gzip测试
echo -n "gzip      "
/usr/bin/time -f "%e" gzip -k -9 "$TEST_FILE" 2>&1 | tail -1 | tr '\n' ' '
ls -lh "${TEST_FILE}.gz" | awk '{printf "%8s  ", $5}'
echo -n "$(echo "scale=2; $(stat -c%s "${TEST_FILE}.gz")*100/$(stat -c%s "$TEST_FILE")" | bc)%  "
/usr/bin/time -v gzip -9 "$TEST_FILE" 2>&1 | grep "Maximum resident" | awk '{print $6}'
rm -f "${TEST_FILE}.gz"

# bzip2测试
echo -n "bzip2    "
/usr/bin/time -f "%e" bzip2 -k -9 "$TEST_FILE" 2>&1 | tail -1 | tr '\n' ' '
ls -lh "${TEST_FILE}.bz2" | awk '{printf "%8s  ", $5}'
echo -n "$(echo "scale=2; $(stat -c%s "${TEST_FILE}.bz2")*100/$(stat -c%s "$TEST_FILE")" | bc)%  "
/usr/bin/time -v bzip2 -9 "$TEST_FILE" 2>&1 | grep "Maximum resident" | awk '{print $6}'
bunzip2 "${TEST_FILE}.bz2" 2>/dev/null

# xz测试
echo -n "xz       "
/usr/bin/time -f "%e" xz -k -9 "$TEST_FILE" 2>&1 | tail -1 | tr '\n' ' '
ls -lh "${TEST_FILE}.xz" | awk '{printf "%8s  ", $5}'
echo -n "$(echo "scale=2; $(stat -c%s "${TEST_FILE}.xz")*100/$(stat -c%s "$TEST_FILE")" | bc)%  "
/usr/bin/time -v xz -9 "$TEST_FILE" 2>&1 | grep "Maximum resident" | awk '{print $6}'
unxz "${TEST_FILE}.xz" 2>/dev/null

# 清理
rm -f "$TEST_FILE"
echo -e "\n测试完成"

实际应用脚本

脚本1:自动备份压缩脚本
#!/bin/bash
# 自动备份和压缩脚本

# 配置
BACKUP_DIR="/backups"
SOURCE_DIRS=("/var/www" "/etc" "/home")
RETENTION_DAYS=30
COMPRESSION_LEVEL=9
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="backup_${DATE}"

# 创建备份目录
mkdir -p "$BACKUP_DIR"

echo "=== 开始备份 $(date) ==="

# 创建临时目录
TEMP_DIR=$(mktemp -d)
echo "临时目录: $TEMP_DIR"

# 备份各个目录
for dir in "${SOURCE_DIRS[@]}"; do
    if [ -d "$dir" ]; then
        dir_name=$(basename "$dir")
        echo "备份: $dir"

        # 使用tar创建归档
        tar -cf "$TEMP_DIR/${dir_name}.tar" -C "$(dirname "$dir")" "$(basename "$dir")" 2>/dev/null

        if [ $? -eq 0 ]; then
            echo "✓ 成功: $dir_name.tar"
        else
            echo "✗ 失败: $dir"
        fi
    else
        echo "警告: 目录不存在 - $dir"
    fi
done

# 压缩备份
echo -e "\n压缩备份文件..."
tar -cjf "$BACKUP_DIR/${BACKUP_NAME}.tar.bz2" -C "$TEMP_DIR" . --use-compress-prog="bzip2 -$COMPRESSION_LEVEL"

if [ $? -eq 0 ]; then
    # 计算压缩率
    original_size=$(du -sb "$TEMP_DIR" | cut -f1)
    compressed_size=$(stat -c%s "$BACKUP_DIR/${BACKUP_NAME}.tar.bz2")
    ratio=$(echo "scale=2; ($original_size - $compressed_size) * 100 / $original_size" | bc)

    echo "✓ 备份压缩完成"
    echo "原始大小: $(numfmt --to=iec $original_size)"
    echo "压缩大小: $(numfmt --to=iec $compressed_size)"
    echo "压缩率: ${ratio}%"

    # 创建MD5校验文件
    md5sum "$BACKUP_DIR/${BACKUP_NAME}.tar.bz2" > "$BACKUP_DIR/${BACKUP_NAME}.md5"
    echo "校验文件: ${BACKUP_NAME}.md5"
else
    echo "✗ 压缩失败"
fi

# 清理临时文件
rm -rf "$TEMP_DIR"
echo "临时文件已清理"

# 删除旧备份
echo -e "\n清理超过${RETENTION_DAYS}天的旧备份..."
find "$BACKUP_DIR" -name "backup_*.tar.bz2" -mtime +$RETENTION_DAYS -delete
find "$BACKUP_DIR" -name "backup_*.md5" -mtime +$RETENTION_DAYS -delete

echo -e "\n=== 备份完成 $(date) ==="
echo "备份文件: $BACKUP_DIR/${BACKUP_NAME}.tar.bz2"
脚本2:日志文件管理工具
#!/bin/bash
# 日志文件压缩和管理工具

LOG_DIR="/var/log"
COMPRESS_AFTER_DAYS=7
DELETE_AFTER_DAYS=90
COMPRESSION_LEVEL=6
MIN_SIZE="10M"

echo "=== 日志文件管理工具 ==="
echo "压缩超过${COMPRESS_AFTER_DAYS}天的日志"
echo "删除超过${DELETE_AFTER_DAYS}天的压缩日志"
echo "最小处理大小: $MIN_SIZE"
echo ""

# 查找需要压缩的日志文件
echo "查找符合条件的日志文件..."
find "$LOG_DIR" -type f -name "*.log" -mtime +$COMPRESS_AFTER_DAYS -size +$MIN_SIZE | while read logfile; do
    echo "处理: $(basename "$logfile")"

    # 检查文件是否正在被使用
    if lsof "$logfile" >/dev/null 2>&1; then
        echo "  ⚠ 文件正在使用,跳过"
        continue
    fi

    # 压缩日志文件
    echo -n "  压缩中..."
    if bzip2 -$COMPRESSION_LEVEL -k "$logfile"; then
        compressed_size=$(stat -c%s "${logfile}.bz2")
        original_size=$(stat -c%s "$logfile")
        ratio=$(echo "scale=1; ($original_size - $compressed_size) * 100 / $original_size" | bc)

        echo "✓ 完成 (压缩率: ${ratio}%)"

        # 清空原日志文件
        > "$logfile"
        echo "  原文件已清空"
    else
        echo "✗ 压缩失败"
    fi
done

echo -e "\n清理旧压缩文件..."
# 删除旧的压缩日志
find "$LOG_DIR" -type f -name "*.log.bz2" -mtime +$DELETE_AFTER_DAYS | while read compressed_log; do
    echo "删除: $(basename "$compressed_log")"
    rm -f "$compressed_log"
done

echo -e "\n磁盘使用统计:"
echo "日志目录: $LOG_DIR"
du -sh "$LOG_DIR"
echo -e "\n.bz2文件统计:"
find "$LOG_DIR" -name "*.bz2" -exec du -ch {} + | tail -1

echo -e "\n=== 处理完成 ==="
脚本3:智能压缩选择器
#!/bin/bash
# 智能压缩工具,根据文件类型选择最佳压缩方式

compress_file() {
    local file="$1"
    local method="$2"

    case $method in
        "bzip2")
            echo "使用bzip2压缩..."
            bzip2 -k -9 "$file"
            ;;
        "gzip")
            echo "使用gzip压缩..."
            gzip -k -9 "$file"
            ;;
        "xz")
            echo "使用xz压缩..."
            xz -k -9 "$file"
            ;;
        "none")
            echo "跳过压缩(小文件)"
            cp "$file" "${file}.copy"
            ;;
    esac
}

analyze_file() {
    local file="$1"

    # 检查文件类型
    file_type=$(file -b "$file")
    file_size=$(stat -c%s "$file")

    echo "文件: $(basename "$file")"
    echo "大小: $(numfmt --to=iec $file_size)"
    echo "类型: $file_type"

    # 根据文件类型和大小推荐压缩方法
    if [[ $file_size -lt 10240 ]]; then
        # 小于10KB的文件不压缩
        echo "推荐: 不压缩(文件太小)"
        echo "压缩方法: none"
        compress_file "$file" "none"
    elif [[ "$file_type" == *"ASCII text"* ]] || [[ "$file_type" == *"UTF-8"* ]]; then
        # 文本文件,bzip2通常表现最好
        echo "推荐: bzip2(文本文件)"
        echo "压缩方法: bzip2"
        compress_file "$file" "bzip2"
    elif [[ "$file_type" == *"executable"* ]] || [[ "$file_type" == *"ELF"* ]]; then
        # 可执行文件,xz通常更好
        echo "推荐: xz(可执行文件)"
        echo "压缩方法: xz"
        compress_file "$file" "xz"
    elif [[ "$file_type" == *"JPEG"* ]] || [[ "$file_type" == *"PNG"* ]] || [[ "$file_type" == *"GIF"* ]]; then
        # 图片文件,已经是压缩格式
        echo "推荐: gzip(图片文件)"
        echo "压缩方法: gzip"
        compress_file "$file" "gzip"
    elif [[ $file_size -gt 104857600 ]]; then
        # 大于100MB的文件,考虑速度
        echo "推荐: gzip(大文件,速度快)"
        echo "压缩方法: gzip"
        compress_file "$file" "gzip"
    else
        # 默认使用bzip2
        echo "推荐: bzip2(默认)"
        echo "压缩方法: bzip2"
        compress_file "$file" "bzip2"
    fi

    echo ""
}

# 主程序
if [ $# -eq 0 ]; then
    echo "用法: $0 文件1 [文件2 ...]"
    echo "示例: $0 *.txt"
    exit 1
fi

echo "=== 智能压缩工具 ==="
echo ""

for file in "$@"; do
    if [ -f "$file" ]; then
        analyze_file "$file"
    else
        echo "警告: 文件不存在 - $file"
    fi
done

echo "=== 压缩完成 ==="
echo ""
echo "结果对比:"
ls -lh *.bz2 *.gz *.xz *.copy 2>/dev/null | head -20

注意事项

重要注意事项:
  • 文件删除:默认压缩/解压后会删除原文件,使用-k选项保留
  • 内存需求:高压缩级别需要大量内存(900KB块需要约9MB内存)
  • 不可恢复:压缩是破坏性的,确保有原始文件备份
  • 二进制文件:对已压缩的二进制文件(如.jpg、.mp4)压缩效果有限
  • 文件权限:压缩不保存文件权限,解压后需要重新设置
  • 大文件处理:处理超大文件时注意磁盘空间和内存限制
  • 版本兼容:不同版本的bzip2压缩文件可能不完全兼容

常见问题

A: 它们是同一个程序的不同名称(硬链接或符号链接):
  • bzip2:默认压缩文件
  • bunzip2:默认解压文件(相当于bzip2 -d)
  • bzcat:解压到标准输出(相当于bzip2 -dc)
验证方法:
# 查看文件链接
ls -l $(which bzip2) $(which bunzip2) $(which bzcat)

# 检查是否同一个inode
ls -i $(which bzip2) $(which bunzip2) $(which bzcat)

# 测试功能相同
echo "test" > test.txt
bzip2 test.txt
bzcat test.txt.bz2
# 输出:test
bunzip2 test.txt.bz2
cat test.txt
# 输出:test

A: 根据需求选择压缩级别:
  • 快速压缩:使用-1或--fast,适合临时文件、测试
  • 日常使用:使用-4到-6,平衡速度和压缩率
  • 最高压缩:使用-9或--best,适合备份、存档
  • 网络传输:考虑使用-2或-3,减少压缩时间
  • 内存限制:小内存系统使用-1到-3
建议:
# 开发环境,快速压缩
bzip2 -1 debug.log

# 生产环境,平衡压缩
bzip2 -4 production.log

# 长期存档,最高压缩
bzip2 -9 archive_data.txt

# 自动选择脚本
if [ $(stat -c%s "file.txt") -gt 1048576 ]; then
    # 大于1MB的文件使用中等压缩
    bzip2 -4 file.txt
else
    # 小文件使用快速压缩
    bzip2 -1 file.txt
fi

A: 各有优势,根据需求选择:
bzip2 gzip
压缩率 更高(文本) 中等
速度 较慢 更快
内存 较多 较少
兼容性 一般 极好
推荐场景 存档、分发、文本 日志、网络、实时
实际选择建议:
# 文本文件压缩 -> bzip2
bzip2 documentation.txt

# 日志文件压缩 -> gzip(更快)
gzip access.log

# 网络传输 -> gzip
cat file.txt | gzip | nc host 8080

# 备份存档 -> bzip2
tar -cjf backup.tar.bz2 /important/data

# 实时压缩 -> gzip
tail -f app.log | gzip > compressed.log.gz

相关命令

bunzip2

解压.bz2文件:

bunzip2 file.bz2
bunzip2 -k archive.bz2
bunzip2 *.bz2
bzcat

查看.bz2文件内容:

bzcat file.bz2
bzcat log.bz2 | grep error
bzcat data.bz2 | head -20
bzip2recover

恢复损坏的.bz2文件:

bzip2recover damaged.bz2
# 生成rec*.bz2文件
bunzip2 rec*.bz2
压缩比较

其他压缩工具:

gzip file.txt       # .gz格式
xz file.txt         # .xz格式
zstd file.txt       # .zst格式
7z a archive.7z file.txt