При неудачном восстановлении OneDrive у меня осталось много файлов и папок с суффиксом «(1)» или «(2)».

Я хотел бы сценарий (Bash хорошо, так как у меня есть MinGW + Cygwin или PowerShell), который будет анализировать все файлы и папки в данной папке (например, "d:\OneDrive" или "/cygdrive/d/OneDrive") и для Для каждого файла или папки проверьте, есть ли один или несколько файлов / папок (в одной и той же подпапке), имя файла или папки которых соответствует регулярному выражению "\1\s *\(\d +\)\.\2", где "\1. "является исходным именем файла / папки без расширения, а \2 является исходным расширением. Затем скрипт должен двоично сравнить исходный файл / папку с каждым из файлов / папок, найденных предыдущим регулярным выражением (рекурсивно в последнем случае), и, если они идентичны, он должен удалить копию (ту, которая имеет более длинное имя файла).

Хотя возможная базовая структура скрипта ясна (два вложенных в циклы, найти для поиска файлов, соответствующих регулярному выражению, diff для сравнения и т.д.) Я недостаточно знаком со сценариями Bash, чтобы удобно соединять части, и в любом случае вполне может быть более эффективная структура (что могло бы помочь, учитывая, что нужно пройти около полумиллиона файлов).

1 ответ1

0

Вот один скрипт, который работает и достаточно эффективен. Обратите внимание, что для работы требуется ровно один пробел до «(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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .