linux sdiff命令

简介: sdiff(side-by-side diff)命令用于并排比较两个文件的差异,直观地显示文件内容的不同之处,特别适合比较源代码、配置文件或文本文件。
并排显示

左右并排比较差异

代码对比

非常适合比较代码

交互模式

合并文件选项

直观清晰

差异一目了然

命令语法

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)中存在
| 行尾 左右文件内容不同
(空) 行尾 左右文件内容相同

基本用法示例

1. 创建测试文件

# 创建第一个文件
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

2. 基本比较

# 并排比较两个文件
sdiff file1.txt file2.txt

# 输出示例:
Apple                               Apple
Banana                              Banana
Cherry                              Cherry
Date                                Date
Elderberry                          Elderberry
Fig                                 Fig
Grape                             | Grapefruit
                                  > Honeydew

# 说明:
# Grape | Grapefruit   - 表示这两行不同(用|分隔)
# > Honeydew           - 表示这行只在右文件中存在

3. 设置输出宽度

# 使用窄宽度输出(适合终端较小时)
sdiff -w 80 file1.txt file2.txt

# 使用更宽的输出(适合大屏幕)
sdiff -w 200 file1.txt file2.txt

# 自动适应终端宽度(使用tput)
sdiff -w $(tput cols) file1.txt file2.txt

高级用法

1. 只显示差异行

# 使用-s选项只显示不同的行
sdiff -s file1.txt file2.txt

# 输出示例:
Grape                             | Grapefruit
                                  > Honeydew

# 结合-w设置宽度
sdiff -s -w 100 file1.txt file2.txt

# 这对于大型文件特别有用,可以快速定位差异

2. 忽略空白差异

# 创建有空白差异的文件
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

3. 忽略特定内容

# 创建有版本信息的文件
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

交互式文件合并

1. 基本合并操作

# 使用-o选项进行交互式合并
sdiff -o merged.txt file1.txt file2.txt

# 交互模式中的命令:
# el - 编辑左列内容
# er - 编辑右列内容
# e  - 编辑当前行
# l  - 选择左列
# r  - 选择右列
# s  - 静默选择相同部分
# v  - 详细模式
# e  - 启动编辑器
# ?  - 显示帮助
# q  - 退出

# 在合并过程中,sdiff会逐行提示你选择:
# % l - 选择左文件内容
# % r - 选择右文件内容
# % s - 保持相同内容

2. 自动合并脚本

#!/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 "合并完成!"

实际应用场景

场景1:代码对比
# 比较两个版本的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
场景2:配置管理
# 比较新旧配置文件
sdiff /etc/ssh/sshd_config /etc/ssh/sshd_config.backup

# 忽略注释行差异
sdiff -I '^#' -I '^$' nginx.conf nginx.conf.new

# 比较环境配置文件
sdiff -i .env.production .env.staging
场景3:数据验证
# 比较数据库导出文件
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

实用脚本和技巧

1. 批量比较目录

#!/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

2. 彩色sdiff输出

#!/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

3. HTML格式输出

#!/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")

EOF # 使用sdiff处理 sdiff -l -w 200 "$FILE1" "$FILE2" | while IFS= read -r line; do echo "" >> "$OUTPUT" # 提取左右部分 left="${line%|*}" right="${line#*|}" if [[ "$line" == *"|"* ]]; then # 不同的行 echo "" >> "$OUTPUT" echo "" >> "$OUTPUT" echo "" >> "$OUTPUT" echo "" >> "$OUTPUT" elif [[ "$line" == *">"* ]]; then # 只在右文件 echo "" >> "$OUTPUT" echo "" >> "$OUTPUT" echo "" >> "$OUTPUT" echo "" >> "$OUTPUT" elif [[ "$line" == *"<"* ]]; then # 只在左文件 echo "" >> "$OUTPUT" echo "" >> "$OUTPUT" echo "" >> "$OUTPUT" echo "" >> "$OUTPUT" else # 相同的行 echo "" >> "$OUTPUT" echo "" >> "$OUTPUT" echo "" >> "$OUTPUT" echo "" >> "$OUTPUT" fi echo "" >> "$OUTPUT" ((line_num++)) done cat >> "$OUTPUT" << EOF
行号$(basename "$FILE1")$(basename "$FILE2")
$line_num$left|$right$line_num>${line%>}$line_num${line%<}<$line_num$line$line

生成时间: $(date)

EOF echo "HTML报告已生成: $OUTPUT"

性能优化和注意事项

注意事项:
  • 比较大型文件时,sdiff可能需要较多内存
  • 输出宽度设置过小可能导致内容截断
  • 交互式合并时,确保有足够的终端高度
  • 对于二进制文件,sdiff可能显示乱码
  • 某些选项可能因系统而异,请查看man手册

处理大文件的技巧

# 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_*

常见问题解答

sdiffdiff -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

学习路径建议

基础

基本使用
  • ✓ 基本比较
  • ✓ 输出理解
  • ✓ 常用选项
  • ✓ 简单合并

进阶

高级技巧
  • ✓ 忽略特定差异
  • ✓ 脚本集成
  • ✓ 彩色输出
  • ✓ 批量处理

精通

实战应用
  • ✓ 性能优化
  • ✓ 自动化工具
  • ✓ 报告生成
  • ✓ 最佳实践
学习建议:
  • 先从简单的文件比较开始练习
  • 熟悉各种输出符号的含义
  • 掌握交互式合并的基本操作
  • 学习如何忽略不重要的差异
  • 将sdiff集成到脚本和工作流中

相关命令和工具

diff

标准差异工具

vimdiff

Vim差异查看器

colordiff

彩色diff输出

meld

图形化比较工具

实用小技巧

技巧1:快速比较配置
# 比较系统配置文件
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:]]*$"
技巧2:集成到脚本
# 在脚本中使用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报告:文件列表、差异统计、每个文件的差异详情,并支持通过邮件发送报告。