Encontre e exclua arquivos duplicados em discos e diretórios diferentes

1

Eu tenho centenas de milhares de arquivos distribuídos em muitos discos externos e discos em computadores e muitos são duplicados. Essa bagunça foi causada por mim criando cópias para proposta de segurança. De vez em quando eu mudava a estrutura de diretórios da minha organização, mas não era replicada em outros lugares onde havia cópias.

Agora, eu tenho um único disco enorme com quase tudo que eu realmente preciso de backups e espelhado na nuvem.

Eu gostaria de uma maneira de excluir tudo de todos os discos distribuídos que já estão no disco grande.

Deixe-me mostrar o cenário:

OldDisk1:

/code/{manystructures}/{manyfiles}
/docs/{manystructures}/{manyfiles}

OldDisk2:

/dev/{another_structures}/{same_files_different_names}
/documents/{another_structures}/{same_files_different_names}

NewHugeDisk:

/home/username/code/{new_strutucture}/{new_files}
/home/username/documents/{new_strutucture}/{new_files}

Alguém conhece uma ferramenta ou uma maneira de fazer algo como "localizar todos os arquivos no OldDisk1 que já estão no NewHugeDisk e excluir"?

Eu olhei para muitas ferramentas (Windows, Mac e Linux como eu tenho esse problema em ambos) livre e pago, mas sem sorte.

E a ideia seria criar um código para fazer isso, mas não sou desenvolvedor. Eu posso fazer códigos pequenos e simples, mas esse tipo de código, eu acho que seria complicado para mim.

Eu apreciarei qualquer ajuda ou idéias sobre isso.

    
por Tuts 14.06.2017 / 01:58

3 respostas

2

Assumindo que você pode usar o Windows como um SO para todo o processo e não gosta de Free Duplicate File Finder (nunca tentei, mas achei mencionado aqui ), você pode usar o PowerShell para obter o que deseja com relativamente pouco esforço. Nota: Eu não sou um profissional de verdade no PowerShell, então tenho certeza que alguém poderia refinar meu código.

Basta abrir o Powershell ISE (ou, se você não tiver isso, usar o Notepad), copiar e colar o seguinte código nele e salvar o arquivo resultante em algum lugar como * .ps1. Você também precisa alterar os valores de $oldpath e $newpath para seus diretórios - basta colocar seus caminhos entre aspas.

# Search-and-Destroy-script
# Get all files of both code-directories:
$oldpath = "Disk1:\code"
$newpath = "DiskNew:\code"

$files_old = Get-ChildItem -Path $oldpath -Recurse -File
$files_new = Get-ChildItem -Path $newpath -Recurse -File

for($i=0; $i -lt $files_old.length; $i++){
    $j=0
    while($true){
        # if last edit time is the same and file-size is the same...
        if($($files_old[$i]).length -eq $($files_new[$j]).length -and $($files_old[$i]).lastWriteTime -eq $($files_new[$j]).lastWriteTime){
            # Get File-Hashes for those files (SHA1 should be enough)
            $files_old_hash = Get-FileHash -Path $($files_old[$i]).FullName -Algorithm SHA1 | ForEach-Object {$_.Hash}
            $files_new_hash = Get-FileHash -Path $($files_new[$j]).FullName -Algorithm SHA1 | ForEach-Object {$_.Hash}
            # if hashes also are the same...
            if($files_old_hash -eq $files_new_hash){
                # remove the old file (-Confirm can be removed so you don't have to approve for every file)
                # if you want to check the files before deletion, you could also just rename them (here we're adding the suffix ".DUPLICATE"
                # Rename-Item -Path $($files_old[$i]).FullName -NewName "$($files_old[$i]).Name.DUPLICATE"
                Remove-Item -Path $($files_old[$i]).FullName -Confirm
                Write-Host "DELETING't$($files_old[$i]).FullName" -ForegroundColor Red
                break
            }
        # if files aren't the same...
        }else{
            # if old_file is compared to all new_files, check next old file
            if($j -ge $files_new.length){
                break
            }
        }
        $j++
    }
}

Em seguida, inicie o script (por meio do clique com o botão direito do mouse, por exemplo) - se isso falhar, verifique se o ExecutionPolicy está definido ( link ).

Eu uso um script quase idêntico para verificar arquivos que já foram copiados (mas possivelmente com nomes alterados). Este código pressupõe que apenas os nomes dos arquivos são diferentes, mas não o conteúdo. A última hora de edição geralmente permanece a mesma, mesmo depois de copiar um arquivo para um novo caminho - ao contrário do tempo de criação. Se o conteúdo for diferente, minha solução falha muito - você pode usar diferentes atributos exclusivos de arquivos (mas quais?) Ou declarar, por exemplo, somente os arquivos tat são menores ou mais antigos (considerando o tempo de edição, novamente) do que os novos arquivos devem ser excluídos.

O que o script faz:

  1. Obtenção de todos os arquivos nas pastas especificadas (e suas subpastas)
  2. obtendo o primeiro arquivo antigo (especificado por $ i) ...
  3. comparando seu tempo de última edição e seu tamanho de arquivo com o do primeiro novo arquivo (especificado por $ j) ...
  4. ... se eles forem iguais, calcula um hash de arquivo para ter certeza de que é definitivamente o mesmo arquivo (sem dúvida, isso pode ser um pouco demais muito esforço para o seu objetivo)
  5. se os hashes forem iguais, o arquivo antigo será excluído (e gravará qual arquivo no terminal) e, em seguida, será iniciado novamente em 2. com o próximo arquivo antigo ...
  6. se os hashes não forem iguais (ou as últimas edições não forem iguais ou os tamanhos dos arquivos não forem iguais), ele será iniciado novamente em 3. com o próximo arquivo novo.
por 14.06.2017 / 02:56
0

Você já tentou usar o software de desduplicação de terceiros?
Eu tentei desduplicação cloudberry e é realmente eficiente como:

  • tem seu próprio mecanismo de dedução para eliminar dados duplicados, economizando muito espaço de armazenamento.
  • Outra vantagem dessas ferramentas é que elas são mais confiáveis e possuem uma técnica dedicada de gerenciamento de recursos.
por 17.06.2017 / 17:37
0

rmlint é um utilitário de linha de comando com opções para fazer exatamente o que você deseja. Ele é executado no Linux e no MacOS. O comando que você quer é:

$ rmlint --progress \
    --must-match-tagged --keep-all-tagged \
    /mnt/OldDisk1 /mnt/OldDisk2 // /mnt/NewHugeDisk

Isto irá encontrar as duplicatas que você deseja. Em vez de excluí-los diretamente, ele cria um script de shell (./rmlint.sh) que você pode revisar, opcionalmente editar e executar para fazer a exclusão desejada.

A opção '--progress' fornece um bom indicador de progresso. O '//' separa 'sem tag' de caminhos 'marcados'; Os caminhos depois de "//" são considerados "marcados". A tag "--must-match-tagged --keep-all-tagged" significa apenas localizar arquivos em caminhos não identificados que possuem uma cópia em um caminho marcado.

Você também pode reduzir esse comando usando o formato curto das opções:

rmlint -g -m -k /mnt/OldDisk1 /mnt/OldDisk2 // /mnt/NewHugeDisk
    
por 09.07.2017 / 23:25