左右并排比较差异
非常适合比较代码
合并文件选项
差异一目了然
sdiff [选项] 文件1 文件2
| 选项 | 说明 |
|---|---|
-l 或 --left-column |
只显示相同的左列,右列显示为空 |
-s 或 --suppress-common-lines |
不显示相同的行 |
-w 宽度 或 --width=宽度 |
设置输出宽度(默认130字符) |
-o 文件 或 --output=文件 |
交互式合并输出到指定文件 |
--diff-program=程序 |
使用指定的diff程序 |
-i 或 --ignore-case |
忽略大小写差异 |
-E 或 --ignore-tab-expansion |
忽略tab扩展的差异 |
-Z 或 --ignore-trailing-space |
忽略行尾空格差异 |
-b 或 --ignore-space-change |
忽略空格数量的变化 |
-W 或 --ignore-all-space |
忽略所有空格差异 |
-B 或 --ignore-blank-lines |
忽略空白行差异 |
-I 正则表达式 |
忽略匹配正则表达式的行 |
--strip-trailing-cr |
去除行尾的回车符 |
-t 或 --expand-tabs |
将tab扩展为空格 |
--help |
显示帮助信息 |
--version |
显示版本信息 |
| 符号 | 位置 | 说明 |
|---|---|---|
< |
行尾 | 该行只在左文件(文件1)中存在 |
> |
行尾 | 该行只在右文件(文件2)中存在 |
| |
行尾 | 左右文件内容不同 |
(空) |
行尾 | 左右文件内容相同 |
# 创建第一个文件
cat > file1.txt << EOF
Apple
Banana
Cherry
Date
Elderberry
Fig
Grape
EOF
# 创建第二个文件(有一些差异)
cat > file2.txt << EOF
Apple
Banana
Cherry
Date
Elderberry
Fig
Grapefruit
Honeydew
EOF
# 并排比较两个文件
sdiff file1.txt file2.txt
# 输出示例:
Apple Apple
Banana Banana
Cherry Cherry
Date Date
Elderberry Elderberry
Fig Fig
Grape | Grapefruit
> Honeydew
# 说明:
# Grape | Grapefruit - 表示这两行不同(用|分隔)
# > Honeydew - 表示这行只在右文件中存在
# 使用窄宽度输出(适合终端较小时)
sdiff -w 80 file1.txt file2.txt
# 使用更宽的输出(适合大屏幕)
sdiff -w 200 file1.txt file2.txt
# 自动适应终端宽度(使用tput)
sdiff -w $(tput cols) file1.txt file2.txt
# 使用-s选项只显示不同的行
sdiff -s file1.txt file2.txt
# 输出示例:
Grape | Grapefruit
> Honeydew
# 结合-w设置宽度
sdiff -s -w 100 file1.txt file2.txt
# 这对于大型文件特别有用,可以快速定位差异
# 创建有空白差异的文件
echo -e "Hello World\n Foo Bar\nTest" > file1.txt
echo -e "Hello World\nFoo Bar \nTest" > file2.txt
# 正常比较(会显示空白差异)
sdiff file1.txt file2.txt
# 忽略空格数量变化
sdiff -b file1.txt file2.txt
# 忽略所有空白差异
sdiff -W file1.txt file2.txt
# 忽略空白行差异
sdiff -B file1.txt file2.txt
# 创建有版本信息的文件
cat > v1.txt << EOF
# Version: 1.0.0
Name: Alice
Age: 25
City: New York
EOF
cat > v2.txt << EOF
# Version: 1.0.1
Name: Alice
Age: 26
City: New York
EOF
# 忽略以#开头的行(版本信息)
sdiff -I '^#' v1.txt v2.txt
# 忽略大小写差异
sdiff -i file1.txt file2.txt
# 忽略时间戳或日期差异
sdiff -I '\d{4}-\d{2}-\d{2}' log1.txt log2.txt
# 使用-o选项进行交互式合并
sdiff -o merged.txt file1.txt file2.txt
# 交互模式中的命令:
# el - 编辑左列内容
# er - 编辑右列内容
# e - 编辑当前行
# l - 选择左列
# r - 选择右列
# s - 静默选择相同部分
# v - 详细模式
# e - 启动编辑器
# ? - 显示帮助
# q - 退出
# 在合并过程中,sdiff会逐行提示你选择:
# % l - 选择左文件内容
# % r - 选择右文件内容
# % s - 保持相同内容
#!/bin/bash
# auto_merge.sh - 自动合并脚本
FILE1="$1"
FILE2="$2"
OUTPUT="$3"
if [ $# -ne 3 ]; then
echo "用法: $0 <文件1> <文件2> <输出文件>"
exit 1
fi
# 使用sdiff进行智能合并
echo "正在合并 $FILE1 和 $FILE2..."
echo "输出到 $OUTPUT"
# 创建合并指令文件
cat > merge_commands.txt << 'EOF'
#!/bin/sdiff-script
# 自动选择规则:
# 1. 如果只有左文件有内容,选择左
# 2. 如果只有右文件有内容,选择右
# 3. 如果内容相同,选择左
# 4. 如果内容不同,启动编辑器
l # 选择左文件
r # 选择右文件
s # 静默选择相同部分
EOF
# 执行合并
sdiff -o "$OUTPUT" "$FILE1" "$FILE2" < merge_commands.txt
# 清理
rm -f merge_commands.txt
echo "合并完成!"
# 比较两个版本的Python脚本
sdiff -w 120 script_v1.py script_v2.py
# 只显示有差异的函数
sdiff -s -I '^#' -I '^$' script_v1.py script_v2.py
# 比较C语言源文件
sdiff -b -B main.c main_new.c | less -R
# 比较新旧配置文件
sdiff /etc/ssh/sshd_config /etc/ssh/sshd_config.backup
# 忽略注释行差异
sdiff -I '^#' -I '^$' nginx.conf nginx.conf.new
# 比较环境配置文件
sdiff -i .env.production .env.staging
# 比较数据库导出文件
sdiff -b -B dump1.sql dump2.sql | head -50
# 比较CSV数据文件(忽略空格)
sdiff -W data_old.csv data_new.csv
# 比较日志文件(忽略时间戳)
sdiff -I '\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}' log1.txt log2.txt
| 工具 | 特点 | 优点 | 缺点 |
|---|---|---|---|
sdiff |
并排显示差异,交互式合并 | 直观,适合逐行比较 | 输出可能较宽 |
diff |
标准差异输出 | 输出简洁,适合脚本处理 | 不够直观 |
vimdiff |
Vim中的差异查看器 | 功能强大,支持编辑 | 需要Vim环境 |
colordiff |
彩色输出的diff | 彩色高亮,易读 | 需要额外安装 |
meld |
图形化比较工具 | 界面友好,功能全面 | 需要图形界面 |
diff -y |
diff的并排输出模式 | 类似sdiff,更标准 | 功能较少 |
# 创建测试文件
echo -e "line1\nline2\nline3" > a.txt
echo -e "line1\nline2 changed\nline3\nline4" > b.txt
# 使用diff(标准输出)
diff a.txt b.txt
# 2c2
# < line2
# ---
# > line2 changed
# 3a4
# > line4
# 使用sdiff(并排输出)
sdiff a.txt b.txt
# line1 line1
# line2 | line2 changed
# line3 line3
# > line4
# 使用diff -y(类似sdiff)
diff -y a.txt b.txt
# line1 line1
# line2 | line2 changed
# line3 line3
# > line4
# 使用vimdiff(需要Vim)
# vimdiff a.txt b.txt
#!/bin/bash
# compare_dirs.sh - 比较两个目录中的文件
DIR1="$1"
DIR2="$2"
if [ $# -ne 2 ]; then
echo "用法: $0 <目录1> <目录2>"
exit 1
fi
# 获取终端宽度
WIDTH=$(tput cols)
let "WIDTH=WIDTH-10"
echo "比较目录: $DIR1 和 $DIR2"
echo "======================================"
# 查找共同的文件
find "$DIR1" -type f -name "*.txt" | while read file1; do
# 获取相对路径
rel_path="${file1#$DIR1/}"
file2="$DIR2/$rel_path"
if [ -f "$file2" ]; then
echo "比较: $rel_path"
echo "--------------------------------------"
# 使用sdiff比较
sdiff -s -w "$WIDTH" "$file1" "$file2" 2>/dev/null
if [ $? -eq 0 ]; then
echo "✓ 文件相同"
else
echo "✗ 文件不同"
fi
echo ""
else
echo "⚠ 文件只在 $DIR1 中存在: $rel_path"
fi
done
#!/bin/bash
# colored_sdiff.sh - 彩色sdiff输出
# 使用ANSI颜色代码
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
sdiff -w $(tput cols) "$1" "$2" | while IFS= read -r line; do
if [[ "$line" =~ \|[[:space:]]*$ ]]; then
# 不同的行 - 黄色
echo -e "${YELLOW}$line${NC}"
elif [[ "$line" =~ \<[[:space:]]*$ ]]; then
# 只在左文件 - 红色
echo -e "${RED}$line${NC}"
elif [[ "$line" =~ \>[[:space:]]*$ ]]; then
# 只在右文件 - 绿色
echo -e "${GREEN}$line${NC}"
elif [[ "$line" =~ ^[[:space:]]*$ ]]; then
# 空白行 - 原样输出
echo "$line"
else
# 相同的行 - 蓝色
echo -e "${BLUE}$line${NC}"
fi
done
#!/bin/bash
# sdiff_to_html.sh - 将sdiff输出转换为HTML
FILE1="$1"
FILE2="$2"
OUTPUT="${3:-diff.html}"
cat > "$OUTPUT" << EOF
文件比较: $(basename "$FILE1") vs $(basename "$FILE2")
文件比较: $(basename "$FILE1") vs $(basename "$FILE2")
行号 $(basename "$FILE1") $(basename "$FILE2")
EOF
# 使用sdiff处理
sdiff -l -w 200 "$FILE1" "$FILE2" | while IFS= read -r line; do
echo "" >> "$OUTPUT"
# 提取左右部分
left="${line%|*}"
right="${line#*|}"
if [[ "$line" == *"|"* ]]; then
# 不同的行
echo "$line_num " >> "$OUTPUT"
echo "$left " >> "$OUTPUT"
echo "| " >> "$OUTPUT"
echo "$right " >> "$OUTPUT"
elif [[ "$line" == *">"* ]]; then
# 只在右文件
echo "$line_num " >> "$OUTPUT"
echo " " >> "$OUTPUT"
echo "> " >> "$OUTPUT"
echo "${line%>} " >> "$OUTPUT"
elif [[ "$line" == *"<"* ]]; then
# 只在左文件
echo "$line_num " >> "$OUTPUT"
echo "${line%<} " >> "$OUTPUT"
echo "< " >> "$OUTPUT"
echo " " >> "$OUTPUT"
else
# 相同的行
echo "$line_num " >> "$OUTPUT"
echo "$line " >> "$OUTPUT"
echo " " >> "$OUTPUT"
echo "$line " >> "$OUTPUT"
fi
echo " " >> "$OUTPUT"
((line_num++))
done
cat >> "$OUTPUT" << EOF
生成时间: $(date)
EOF
echo "HTML报告已生成: $OUTPUT"
# 1. 使用less分页查看
sdiff large1.txt large2.txt | less -S
# 2. 只比较前N行
head -1000 large1.txt > temp1.txt
head -1000 large2.txt > temp2.txt
sdiff temp1.txt temp2.txt
rm temp1.txt temp2.txt
# 3. 使用diff先快速判断是否相同
if ! diff -q file1.txt file2.txt > /dev/null; then
echo "文件不同,开始详细比较..."
sdiff -s file1.txt file2.txt | head -50
fi
# 4. 使用split分割大文件
split -l 1000 large1.txt part1_
split -l 1000 large2.txt part2_
for i in part1_*; do
j="part2_${i#part1_}"
if [ -f "$j" ]; then
sdiff "$i" "$j"
fi
done
rm part1_* part2_*
sdiff和diff -y都提供并排比较,但有一些区别:
# 1. 输出格式略有不同
# sdiff使用 | < > 作为分隔符
# diff -y使用 | < > 但格式更紧凑
# 2. 功能差异
# sdiff有交互式合并功能(-o选项)
# diff -y没有交互功能
# 3. 选项名称不同
# sdiff: -w 设置宽度
# diff: --width 设置宽度
# 4. 默认行为
# sdiff默认显示所有行
# diff -y默认显示所有行
# 5. 实际使用建议
# 如果需要交互合并:使用sdiff
# 如果只需要查看差异:两者都可以
# 如果在意POSIX兼容性:使用diff -y
# 示例对比:
diff -y --suppress-common-lines file1.txt file2.txt
# 相当于
sdiff -s file1.txt file2.txt
有几种方法可以让sdiff输出彩色:
# 方法1:使用colordiff包装
sdiff file1.txt file2.txt | colordiff
# 方法2:使用自定义脚本(如前文所示)
./colored_sdiff.sh file1.txt file2.txt
# 方法3:使用vim的dif功能
vim -d file1.txt file2.txt
# 或
vimdiff file1.txt file2.txt
# 方法4:使用diff-so-fancy(需要安装)
sdiff file1.txt file2.txt | diff-so-fancy
# 方法5:使用git diff(如果文件在git中)
git diff --no-index --color-words file1.txt file2.txt
# 方法6:使用icdiff(需要安装)
icdiff file1.txt file2.txt
# 安装彩色工具
# Ubuntu/Debian
sudo apt-get install colordiff vim
# CentOS/RHEL
sudo yum install colordiff vim
# macOS
brew install colordiff diff-so-fancy icdiff
sdiff主要用于文本文件,对于二进制文件,可以使用其他工具:
# 1. 使用cmp比较二进制文件
cmp -l binary1.bin binary2.bin
# 2. 使用hexdump转换为文本再比较
hexdump -C binary1.bin > hex1.txt
hexdump -C binary2.bin > hex2.txt
sdiff hex1.txt hex2.txt
# 3. 使用xxd(类似hexdump)
xxd binary1.bin > xxd1.txt
xxd binary2.bin > xxd2.txt
sdiff xxd1.txt xxd2.txt
# 4. 使用od(八进制转储)
od -x binary1.bin > od1.txt
od -x binary2.bin > od2.txt
sdiff od1.txt od2.txt
# 5. 使用vbindiff(可视化二进制比较)
# 需要安装
sudo apt-get install vbindiff
vbindiff binary1.bin binary2.bin
# 6. 使用radare2(逆向工程工具)
radiff2 binary1.bin binary2.bin
# 1. 先使用diff -q快速判断是否相同
if diff -q file1.txt file2.txt > /dev/null 2>&1; then
echo "文件相同"
else
sdiff file1.txt file2.txt
fi
# 2. 只比较文件的一部分
# 比较前1000行
head -1000 file1.txt > temp1
head -1000 file2.txt > temp2
sdiff temp1 temp2
rm temp1 temp2
# 3. 使用更快的diff算法
sdiff --diff-program="diff --speed-large-files" large1.txt large2.txt
# 4. 忽略不重要的差异(减少比较工作量)
sdiff -b -B file1.txt file2.txt # 忽略空格和空行
# 5. 使用并行处理(对于多个文件)
# 使用GNU parallel
parallel sdiff -s {} {= s/_v1/_v2/ =} ::: *_v1.txt
# 6. 缓存比较结果
if [ ! -f "diff_cache.txt" ] || [ "file1.txt" -nt "diff_cache.txt" ] || [ "file2.txt" -nt "diff_cache.txt" ]; then
sdiff file1.txt file2.txt > diff_cache.txt
fi
cat diff_cache.txt
diff标准差异工具
vimdiffVim差异查看器
colordiff彩色diff输出
meld图形化比较工具
# 比较系统配置文件
sdiff -b -B -I '^#' /etc/ssh/sshd_config /etc/ssh/sshd_config.backup
# 比较nginx配置
sdiff -s -w $(tput cols) /etc/nginx/sites-available/default /etc/nginx/sites-available/default.new
# 比较环境变量
sdiff -i .bashrc .bashrc.backup | grep -v "^[[:space:]]*$"
# 在脚本中使用sdiff检查更改
CONFIG_FILE="/etc/myapp/config.conf"
BACKUP_FILE="/etc/myapp/config.conf.backup"
if ! sdiff -s "$CONFIG_FILE" "$BACKUP_FILE" > /dev/null; then
echo "配置已更改,差异如下:"
sdiff -s -w 100 "$CONFIG_FILE" "$BACKUP_FILE"
# 询问是否恢复
read -p "是否恢复备份?(y/n): " choice
if [ "$choice" = "y" ]; then
cp "$BACKUP_FILE" "$CONFIG_FILE"
fi
fi
创建一个脚本,使用sdiff自动比较两个目录中的所有文本文件,生成包含以下内容的HTML报告:文件列表、差异统计、每个文件的差异详情,并支持通过邮件发送报告。