Script para deduplicação de arquivos e pastas com um sufixo específico

0

Uma restauração mal feita do OneDrive me deixou muitos arquivos e pastas com o sufixo "(1)" ou "(2)".

Eu gostaria de um script (Bash é bom como eu tenho MinGW + Cygwin, ou PowerShell) que iria analisar todos os arquivos e pastas dentro de uma determinada pasta (por exemplo, "d: \ OneDrive" ou "/ cygdrive / d / OneDrive" ) e para cada arquivo ou pasta, veja se há um ou mais arquivos / pastas (na mesma subpasta) cujo nome de arquivo / pasta corresponde ao regex "\ 1 \ s * \ (\ d + \) \. \ 2" onde "\ 1" é o nome do arquivo / pasta original sem extensão e \ 2 é a extensão original. Em seguida, o script deve comparar o arquivo binário original / pasta para cada um dos arquivos / pastas encontradas pelo regex anterior (recursivamente no último caso) e se eles são idênticos, deve excluir a cópia (aquele com o nome de arquivo mais longo).

Enquanto uma possível estrutura básica do script é clara (dois aninhados para loops, encontrar para encontrar arquivos correspondentes a regex, diff para comparação etc.) Eu não estou familiarizado o suficiente com scripts Bash para confortavelmente juntar as peças, e pode haver uma estrutura mais eficiente em qualquer caso (o que ajudaria, dado que existem cerca de meio milhão de arquivos para passar).

    
por cfp 02.08.2018 / 11:58

1 resposta

0

Aqui está um script que funciona e é razoavelmente eficiente. Note que ele requer precisamente que um espaço tenha sido adicionado antes do "(1)" e nenhum tenha sido adicionado depois para que ele funcione.

#!/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
    
por 03.08.2018 / 13:49