将多个目录的权限信息统计并进行比对的Shell脚本

1、功能说明

该脚本主要提供目录权限信息收集与对比功能,支持处理百万级文件目录的统计分析,分为两个核心模块:

  1. 权限信息收集 (collect):收集指定路径的信息(绝对路径、权限码、属主、属组)自动生成日志(``diff_.log`)
  2. 智能日志对比 (compare):对比脚本收集信息生成的日志中,相同路径的权限差异

2、使用示例

  • CentOS 7+
  • Ubuntu 18.04+
# 收集数据
./script.sh collect /path/to/directory

# 对比日志
./script.sh compare diff_host1.log diff_host2.log diff_host3.log

3、脚本内容:

#!/bin/bash

# 功能1:收集目录权限信息
function collect_info() {
    target_dir="$1"
    [ ! -d "$target_dir" ] && echo "目录不存在" && exit 1

    host=$(hostname)
    base_name="diff_${host}"
    suffix=".log"
    counter=1
    logfile="${base_name}${suffix}"

    while [ -f "$logfile" ]; do
        logfile="${base_name}_${counter}${suffix}"
        ((counter++))
    done

    find "$(realpath "$target_dir")" -exec stat -c "+-%n %a %U %G" {} \; 2>/dev/null | 
        sed 's/\/\//\//g' > "$logfile"
    echo "日志已生成:$logfile"
}

# 功能2:对比日志差异(优化版)
function compare_logs() {
    shift
    log_files=("$@")
    [ ${#log_files[@]} -lt 2 ] && echo "需要至少2个日志文件" && exit 1

    diff_detected=0
    diff_log="diff_result_$(date +%Y%m%d%H%M%S).log"

    awk '
    BEGIN { all_same = 1 }
    {
        path=$2
        gsub(/^+-/, "", path)
        key=path
        if (!(key in data)) {
            data[key]["count"] = 0
        }
        data[key]["count"]++
        data[key][data[key]["count"]] = $3 OFS $4 OFS $5
        files[data[key]["count"]] = FILENAME
    }
    END {
        for (path in data) {
            if (data[path]["count"] == 1) {
                all_same = 0
                exit
            }
            for (i=2; i<=data[path]["count"]; i++) {
                if (data[path][i] != data[path][1]) {
                    all_same = 0
                    exit
                }
            }
        }
        if (all_same == 1) {
            exit 0
        }
        
        print "差异路径 | 权限 | 属主 | 属组 | 来源文件" > "'"$diff_log"'"
        for (path in data) {
            if (data[path]["count"] == 1) {
                printf "%s | %s | (仅存在于 %s)\n", 
                    path, data[path][1], files[1] >> "'"$diff_log"'"
                continue
            }
            
            is_diff = 0
            for (i=2; i<=data[path]["count"]; i++) {
                if (data[path][i] != data[path][1]) {
                    is_diff = 1
                    break
                }
            }
            
            if (is_diff) {
                for (i=1; i<=data[path]["count"]; i++) {
                    printf "%s | %s | %s\n", 
                        path, data[path][i], files[i] >> "'"$diff_log"'"
                }
                print "------" >> "'"$diff_log"'"
            }
        }
    }' "${log_files[@]}"

    if [ $? -eq 0 ]; then
        echo "差异分析完成:所有路径权限属性完全相同"
        rm -f "$diff_log" 2>/dev/null
    else
        echo "差异分析完成:结果见:$diff_log"
    fi
}

# 主逻辑
case $1 in
    collect)
        collect_info "$2"
        ;;
    compare)
        compare_logs "$@"
        ;;
    *)
        echo "用法:"
        echo "  收集模式:$0 collect <目录路径>"
        echo "  对比模式:$0 compare <日志文件1> <日志文件2> [...]"
        exit 1
        ;;
esac