用于对具有特定后缀的文件和文件夹进行重复数据删除的脚本

用于对具有特定后缀的文件和文件夹进行重复数据删除的脚本

拙劣的 OneDrive 恢复导致我留下了许多带有“ (1)”或“ (2)”后缀的文件和文件夹。

我想要一个脚本(Bash 就很好,因为我有 MinGW + Cygwin,或者 PowerShell),它可以解析给定文件夹(例如“d:\OneDrive”或“/cygdrive/d/OneDrive”)内的所有文件和文件夹,并且对于每个文件或文件夹,查看是否有一个或多个文件/文件夹(在同一个子文件夹中)的文件/文件夹名称与正则表达式“\1\s*\(\d+\)\.\2”匹配,其中“\1”是没有扩展名的原始文件/文件夹名称,\2 是原始扩展名。然后,脚本应该将原始文件/文件夹与前一个正则表达式找到的每个文件/文件夹进行二进制比较(在后一种情况下是递归比较),如果它们相同,则应该删除副本(文件名较长的副本)。

虽然脚本的可能基本结构很清晰(两个嵌套的 for 循环、用于查找与正则表达式匹配的文件的 find、用于比较的 diff 等),但我对 Bash 脚本不够熟悉,无法轻松地将各个部分组合在一起,而且无论如何都可能存在更高效的结构(这会有所帮助,因为有大约 50 万个文件需要处理)。

答案1

这是一个可以运行且相当高效的脚本。请注意,它确实要求在“(1)”之前添加一个空格,并且在之后不添加任何空格才能运行。

#!/usr/bin/bash
IFS=$'\n';
set -f
#Go deepest first to deal with copies within copied folders.
for copy in $(find . -regextype posix-egrep -regex "^.*\ \([0-9]+\)\s*(\.[^/.]*)?$" | awk '{print length($0)"\t"$0}' | sort -rnk1 | cut -f2-); do
    orig=$(rev <<< "$copy" | sed -E 's/\)[0-9]+\(\ //' | rev)
    if [ "$orig" != "$copy" ]; then
        if [ -f "$orig" ]; then
            if [ -f "$copy" ]; then
                echo "File pair: $orig $copy"
                if diff -q "$orig" "$copy" &>/dev/null; then
                    echo "Removing file: $copy"
                    rm -f "$copy";
                fi
            fi           
        fi
        if [ -d "$orig" ]; then
            if [ -d "$copy" ]; then
                echo "Folder pair: $orig $copy"
                if rmdir "$copy" &>/dev/null; then
                    #If the "copy" was an empty directory then we've removed it and so we're done.
                    echo "Removed empty folder: $copy"
                else
                    #Non-destructively ensure that both folders have the same files at least.                    
                    rsync -aHAv --ignore-existing "$orig/" "$copy" &>/dev/null
                    rsync -aHAv --ignore-existing "$copy/" "$orig" &>/dev/null
                    if diff -qr "$orig" "$copy" &>/dev/null; then
                        echo "Removing folder: $copy"
                        rm -rf "$copy";
                    fi            
                fi
            fi
        fi
    fi
done
unset IFS;
set +f

相关内容