linux diffstat命令

命令简介

diffstat 命令用于读取 diff 命令的输出,并显示插入、删除和修改行的统计信息。它通过图形化的方式展示文件变更的规模,是代码审查、补丁分析和版本控制中非常有用的工具。

语法

diff [选项] | diffstat [选项]

或者直接处理文件:

diffstat [选项] 补丁文件

常用选项

选项 说明
-c 在输出中添加注释
-e 将输出重定向到sed脚本
-f 指定输出格式(0-4)
-k 抑制合并diff中的目录名
-m 仅显示修改统计,不显示图形
-n 指定文件名长度
-p 在文件名中包含路径
-u 不排序输出
-w 指定输出宽度
-V 显示版本信息

输出格式说明

1. 默认输出格式
file1.txt | 5 +++++
file2.c   | 10 +++++++++-
file3.py  |  3 ++-
3 files changed, 17 insertions(+), 2 deletions(-)

说明:

  • +++++ 表示添加的行数
  • - 表示删除的行数
  • 数字显示具体的变更统计
2. 详细格式(-f 1)
file1.txt:
 |  5 +++++
file2.c:
 | 10 +++++++++-
file3.py:
 |  3 ++-
17 insertions, 2 deletions in 3 files

基本用法

1. 基本diff统计
# 创建测试文件
echo -e "line1\nline2\nline3\nline4\nline5" > file1.txt
echo -e "line1\nmodified\nline3\nline4\nline5\nline6" > file2.txt

# 使用diff管道到diffstat
diff -u file1.txt file2.txt | diffstat

# 输出示例:
# file1.txt | 1 -
# file2.txt | 2 ++
# 2 files changed, 2 insertions(+), 1 deletion(-)
2. 直接处理补丁文件
# 生成补丁文件
diff -u file1.txt file2.txt > changes.patch

# 使用diffstat分析补丁
diffstat changes.patch

# 或者
cat changes.patch | diffstat
3. 控制输出宽度
# 指定输出宽度为80字符
diff -u file1.txt file2.txt | diffstat -w 80

# 自动适应终端宽度
diff -u file1.txt file2.txt | diffstat -w 0
4. 显示修改统计
# 仅显示数字统计,不显示图形
diff -u file1.txt file2.txt | diffstat -m

# 输出示例:
# file1.txt | 1 | 1
# file2.txt | 1 | 2
# 2 files changed, 2 insertions, 1 deletion

实际应用场景

场景1:代码补丁分析
# 分析Git提交的变更统计
git show --pretty=format:"" --stat HEAD | diffstat

# 或者直接使用git的diff
git diff HEAD~1 HEAD | diffstat

# 分析特定分支的差异
git diff main..feature-branch | diffstat -w 100
场景2:软件包更新分析
# 下载两个版本的源码包
wget http://example.com/software-1.0.tar.gz
wget http://example.com/software-1.1.tar.gz

# 解压并比较
tar -xzf software-1.0.tar.gz
tar -xzf software-1.1.tar.gz
diff -Nur software-1.0 software-1.1 | diffstat

# 输出示例:
# Makefile          |  4 ++--
# src/main.c        | 15 ++++++++++++++-
# src/utils.c       |  7 +++++++
# 3 files changed, 23 insertions(+), 2 deletions(-)
场景3:代码审查准备
# 生成详细的代码变更报告
git diff --cached | diffstat -f 1 -w 120 > code_review_stats.txt

# 查看报告
cat code_review_stats.txt

# 输出示例:
# src/controllers/user_controller.py:
#  | 45 +++++++++++++++++++++++++++++++++++++++++++++
# src/models/user.py:
#  | 12 +++++++++++-
# src/templates/user.html:
#  |  7 +++++++
# 68 insertions, 1 deletion in 3 files
场景4:持续集成脚本
#!/bin/bash
# 在CI脚本中使用diffstat

echo "=== 代码变更统计 ==="
git diff $BASE_SHA $HEAD_SHA | diffstat -w 100

echo ""
echo "=== 文件变更详情 ==="
git diff --name-status $BASE_SHA $HEAD_SHA

# 输出示例:
# === 代码变更统计 ===
# src/api.js      | 20 ++++++++++++++++++++
# src/components/ | 15 +++++++++++++++
# 2 files changed, 35 insertions(+)
#
# === 文件变更详情 ===
# M src/api.js
# A src/components/NewComponent.js

高级用法

1. 自定义输出格式
# 格式0:默认格式
diff -u file1 file2 | diffstat -f 0

# 格式1:详细格式
diff -u file1 file2 | diffstat -f 1

# 格式2:CSV格式
diff -u file1 file2 | diffstat -f 2

# 格式4:包含路径的格式
diff -u file1 file2 | diffstat -f 4 -p 1
2. 批量分析多个补丁
# 分析目录下所有补丁文件
for patch in patches/*.patch; do
    echo "=== $patch ==="
    diffstat -w 80 < "$patch"
    echo
done

# 或者使用find
find patches/ -name "*.patch" -exec echo "=== {} ===" \; -exec diffstat -w 80 {} \;
3. 与其他工具结合
# 生成HTML格式的报告
diff -u old new | diffstat -f 0 | \
awk 'BEGIN {print ""} {print ""} END {print "
" $1 "" $2 "
"}' > report.html # 使用sed处理输出 diff -u file1 file2 | diffstat -e > changes.sed # 生成JSON格式输出 diff -u file1 file2 | diffstat -m | \ awk 'BEGIN {print "["} /files changed/ {next} {if(NR>1) printf ","; printf "{\"file\":\"%s\",\"insertions\":%s,\"deletions\":%s}", $1, $2, $3} END {print "]"}' > changes.json
4. 监控代码库变更
#!/bin/bash
# 监控脚本:定期检查代码变更

LAST_COMMIT=$(git rev-parse HEAD)

while true; do
    git fetch origin
    NEW_COMMIT=$(git rev-parse origin/main)

    if [ "$LAST_COMMIT" != "$NEW_COMMIT" ]; then
        echo "检测到新的提交: $(date)"
        echo "变更统计:"
        git diff $LAST_COMMIT $NEW_COMMIT | diffstat -w 100
        LAST_COMMIT=$NEW_COMMIT
        echo "----------------------------------------"
    fi

    sleep 300  # 5分钟检查一次
done

注意事项

  • diffstat通常需要diff的统一格式(-u)输入以获得最佳效果
  • 对于二进制文件的变更,统计可能不准确
  • 使用-w选项可以控制输出宽度,避免长文件名被截断
  • 在脚本中使用时,结合-m选项可以获得更易解析的输出
  • diffstat不会修改原始文件,只是提供统计信息
  • 对于大型代码库,可以考虑使用更专业的代码分析工具