Linux系统查找同名文件管理删除操作Shell脚本


#!/bin/bash

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # 无颜色

# 显示帮助信息
show_help() {
    echo -e "${BLUE}同名文件查找和管理工具${NC}"
    echo "用法: $0 [选项] [目录]"
    echo "选项:"
    echo "  -h, --help     显示此帮助信息"
    echo "  -r, --recursive递归查找子目录"
    echo "  -d, --delete   直接进入删除模式"
    echo "  -s, --size     显示文件大小"
    echo "  -t, --time     显示修改时间"
    echo ""
    echo "示例:"
    echo "  $0 ~/Downloads          # 查找指定目录"
    echo "  $0 -r ~/Documents       # 递归查找"
    echo "  $0 -s -t .              # 显示详细信息"
}

# 查找同名文件
find_duplicate_names() {
    local target_dir="$1"
    local recursive="$2"
    
    echo -e "${BLUE}正在扫描目录: $target_dir${NC}"
    echo -e "${BLUE}================================${NC}"
    
    # 使用不同的find命令根据递归选项
    if [ "$recursive" = true ]; then
        find_cmd="find \"$target_dir\" -type f"
    else
        find_cmd="find \"$target_dir\" -maxdepth 1 -type f"
    fi
    
    # 查找所有文件并统计同名文件
    eval $find_cmd | while IFS= read -r file; do
        filename=$(basename "$file")
        echo "$filename|$file"
    done | sort | uniq -c | grep -v '^ *1 ' | while read count line; do
        filename=$(echo "$line" | cut -d'|' -f1)
        filepath=$(echo "$line" | cut -d'|' -f2)
        
        # 统计同名文件数量
        actual_count=$(eval $find_cmd -name "$filename" | wc -l)
        if [ $actual_count -gt 1 ]; then
            echo -e "${YELLOW}\n发现 $actual_count 个同名文件: $filename${NC}"
            
            # 显示每个文件的信息
            file_num=1
            eval $find_cmd -name "$filename" | while IFS= read -r duplicate; do
                if [ "$show_size" = true ]; then
                    size=$(du -h "$duplicate" | cut -f1)
                    size_info="大小: $size"
                else
                    size_info=""
                fi
                
                if [ "$show_time" = true ]; then
                    mtime=$(stat -c "%y" "$duplicate" | cut -d'.' -f1)
                    time_info="修改时间: $mtime"
                else
                    time_info=""
                fi
                
                echo -e "${GREEN}[$file_num] ${duplicate}${NC}"
                if [ -n "$size_info" ] || [ -n "$time_info" ]; then
                    echo "    $size_info $time_info"
                fi
                file_num=$((file_num + 1))
            done
        fi
    done
}

# 删除文件处理
handle_deletion() {
    local target_dir="$1"
    local recursive="$2"
    
    echo -e "${RED}\n警告: 删除模式${NC}"
    echo -e "${RED}================================${NC}"
    
    # 查找所有文件
    if [ "$recursive" = true ]; then
        find_cmd="find \"$target_dir\" -type f"
    else
        find_cmd="find \"$target_dir\" -maxdepth 1 -type f"
    fi
    
    # 收集所有文件名
    eval $find_cmd | while IFS= read -r file; do
        filename=$(basename "$file")
        echo "$filename|$file"
    done | sort | uniq -c | grep -v '^ *1 ' | while read count line; do
        filename=$(echo "$line" | cut -d'|' -f1)
        filepath=$(echo "$line" | cut -d'|' -f2)
        
        # 统计同名文件
        duplicates=($(eval $find_cmd -name "$filename"))
        actual_count=${#duplicates[@]}
        
        if [ $actual_count -gt 1 ]; then
            echo -e "${YELLOW}\n处理文件: $filename (共 $actual_count 个)${NC}"
            
            # 显示文件列表
            for i in "${!duplicates[@]}"; do
                echo -e "${GREEN}[$((i+1))] ${duplicates[i]}${NC}"
            done
            
            # 获取用户选择
            echo -e "${BLUE}请选择操作:${NC}"
            echo "  [0] 跳过此文件"
            echo "  [1-$actual_count] 删除对应文件"
            echo "  [a] 删除所有同名文件"
            echo "  [k] 保留所有并继续"
            
            read -p "请输入选择: " choice
            
            case $choice in
                0)
                    echo "跳过 $filename"
                    ;;
                a)
                    echo -e "${RED}删除所有 $actual_count 个文件${NC}"
                    for file in "${duplicates[@]}"; do
                        rm -v "$file"
                    done
                    ;;
                k)
                    echo "保留所有文件"
                    ;;
                [1-9]*)
                    if [[ $choice =~ ^[0-9]+$ ]] && [ $choice -ge 1 ] && [ $choice -le $actual_count ]; then
                        file_to_delete="${duplicates[$((choice-1))]}"
                        echo -e "${RED}删除文件: $file_to_delete${NC}"
                        rm -v "$file_to_delete"
                    else
                        echo "无效的选择"
                    fi
                    ;;
                *)
                    echo "无效的输入"
                    ;;
            esac
        fi
    done
}

# 主函数
main() {
    # 默认值
    target_dir="."
    recursive=false
    delete_mode=false
    show_size=false
    show_time=false
    
    # 解析参数
    while [[ $# -gt 0 ]]; do
        case $1 in
            -h|--help)
                show_help
                exit 0
                ;;
            -r|--recursive)
                recursive=true
                shift
                ;;
            -d|--delete)
                delete_mode=true
                shift
                ;;
            -s|--size)
                show_size=true
                shift
                ;;
            -t|--time)
                show_time=true
                shift
                ;;
            -*)
                echo -e "${RED}未知选项: $1${NC}"
                show_help
                exit 1
                ;;
            *)
                target_dir="$1"
                shift
                ;;
        esac
    done
    
    # 检查目录是否存在
    if [ ! -d "$target_dir" ]; then
        echo -e "${RED}错误: 目录不存在: $target_dir${NC}"
        exit 1
    fi
    
    # 检查是否安装必要工具
    if ! command -v find &> /dev/null; then
        echo -e "${RED}错误: find 命令未找到${NC}"
        exit 1
    fi
    
    # 执行相应模式
    if [ "$delete_mode" = true ]; then
        handle_deletion "$target_dir" "$recursive"
    else
        find_duplicate_names "$target_dir" "$recursive"
        
        # 询问是否进入删除模式
        echo -e "\n${BLUE}================================${NC}"
        read -p "是否要进入删除模式?(y/N): " answer
        if [[ $answer =~ ^[Yy]$ ]]; then
            handle_deletion "$target_dir" "$recursive"
        fi
    fi
    
    echo -e "${GREEN}\n操作完成!${NC}"
}

# 执行主函数
main "$@"

使用方法

1.保存脚本

# 将脚本保存为 find_duplicates.sh
chmod +x find_duplicates.sh

2.基本用法

# 在当前目录查找同名文件
./find_duplicates.sh

# 在指定目录查找
./find_duplicates.sh ~/Downloads

# 递归查找
./find_duplicates.sh -r ~/Documents

显示详细信息

# 显示文件大小和修改时间
./find_duplicates.sh -s -t .

# 直接进入删除模式
./find_duplicates.sh -d ~/Downloads

 


文档仓库 » Linux系统查找同名文件管理删除操作Shell脚本