MST

星途 面试题库

面试题:Bash文件比较与同步的自定义优化

在一个大规模集群环境中,需要频繁比较和同步大量分布式文件。现要求基于Bash编写一个脚本,利用 `diff` 和 `rsync` 的特性,对文件比较和同步过程进行优化。例如,在比较文件时可以先基于文件大小和哈希值快速筛选出大概率不同的文件,然后再精细比较;同步时能够智能处理网络中断等异常情况,实现断点续传等功能。请阐述实现思路并写出关键代码片段。
11.0万 热度难度
编程语言Bash

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 文件筛选
    • 先通过 stat 命令获取文件大小,对于大小不同的文件直接判定为不同。
    • 对于大小相同的文件,使用 md5sumsha256sum 计算哈希值,比较哈希值进一步筛选出大概率不同的文件。
  2. 精细比较
    • 对于经过上述筛选后仍不确定的文件,使用 diff 命令进行精细比较。
  3. 同步优化
    • 使用 rsync--partial--append 选项实现断点续传功能,处理网络中断等异常情况。
    • 利用 rsync--progress 选项查看同步进度。

关键代码片段

#!/bin/bash

# 源目录和目标目录
source_dir="/path/to/source"
target_dir="/path/to/target"

# 比较函数
compare_files() {
    local file1=$1
    local file2=$2
    local size1=$(stat -c%s "$file1")
    local size2=$(stat -c%s "$file2")
    if [ "$size1" -ne "$size2" ]; then
        return 1
    fi
    local hash1=$(md5sum "$file1" | awk '{print $1}')
    local hash2=$(md5sum "$file2" | awk '{print $1}')
    if [ "$hash1" != "$hash2" ]; then
        return 1
    fi
    # 如果哈希值相同,进行精细比较
    diff -q "$file1" "$file2" >/dev/null
    return $?
}

# 同步文件函数
sync_file() {
    local source_file=$1
    local target_file=$2
    rsync -avz --partial --append --progress "$source_file" "$target_file"
}

# 遍历源目录
for source_file in $source_dir/*; do
    if [ -f "$source_file" ]; then
        relative_path=${source_file#$source_dir/}
        target_file=$target_dir/$relative_path
        if [ -f "$target_file" ]; then
            if compare_files "$source_file" "$target_file"; then
                echo "Files are identical: $source_file"
            else
                echo "Files are different: $source_file, syncing..."
                sync_file "$source_file" "$target_file"
            fi
        else
            echo "File missing in target: $source_file, syncing..."
            sync_file "$source_file" "$target_file"
        fi
    fi
done

# 处理目标目录中多余的文件
for target_file in $target_dir/*; do
    if [ -f "$target_file" ]; then
        relative_path=${target_file#$target_dir/}
        source_file=$source_dir/$relative_path
        if [ ! -f "$source_file" ]; then
            echo "File extra in target: $target_file, removing..."
            rm "$target_file"
        fi
    fi
done