Estou tentando encontrar uma maneira de verificar dentro de um determinado diretório arquivos duplicados (mesmo com nomes diferentes) e substituí-los por links simbólicos apontando para a primeira ocorrência. Eu tentei com, fdupes
mas apenas lista essas duplicatas.
Esse é o contexto: estou personalizando um tema de ícone ao meu gosto, e descobri que muitos ícones, mesmo que tenham nomes diferentes e locais diferentes dentro de sua pasta pai, e sejam usados para propósitos diferentes, basicamente são os mesmos cenário. Como aplicar a mesma modificação vinte ou trinta vezes é redundante quando apenas uma é realmente necessária, quero manter apenas uma imagem e vincular todas as outras.
Como exemplo, se eu executar fdupes -r ./
dentro do diretório testdir
, ele poderá retornar os seguintes resultados:
./file1.png
./file2.png
./subdir1/anotherfile.png
./subdir1/subdir2/yetanotherfile.png
Dada essa saída, eu gostaria de manter apenas o arquivo file1.png
, excluir todos os outros e substituí-los por links simbólicos apontando para ele, mantendo todos os nomes de arquivos originais. Portanto file2.png
, manterá seu nome, mas se tornará um link para, em file1.png
vez de ser uma duplicata.
Esses links não devem apontar para um caminho absoluto, mas devem ser relativos ao testdir
diretório pai ; ou seja yetanotherfile.png
, será apontar para ../../file1.png
, não para/home/testuser/.icons/testdir/file1.png
Estou interessado tanto em soluções que envolvem uma GUI e CLI. Não é obrigatório usar o fdupes
que citei, porque é uma ferramenta que eu conheço, mas estou aberto a soluções que usam outras ferramentas também.
Tenho certeza de que um script bash para lidar com tudo isso não deve ser tão difícil de criar, mas não sou especialista o suficiente para descobrir como escrevê-lo.
fonte
v1.51
(Ubuntu 14.04.2 LTS).jdupes
em github.com/jbruchon/jdupes tem a-L
opção que faz a ligação física desejada de conjuntos duplicados.${line//…/}
peça não estava funcionando para mim, então fiz uma maneira mais limpa de obter o primeiro arquivo "mestre" para o hardlink.rsync
um tipo diferente de sistema de arquivos? Ou se o sistema de arquivos não preservar a hierarquia, por exemplo, é um servidor de backup que coloca tudo sob controle/«machine-name»/...
? Ou se você deseja restaurar do backup? Não vejo como os hardlinks serão preservados aqui. Softlinks relativos teriam melhores chances de sobreviver, eu acho.Se você não gosta de muitos scripts, posso recomendar o rdfind . O qual examinará os diretórios especificados em busca de arquivos duplicados e os vinculará de forma flexível ou virtual. Eu o usei para desduplicar meu diretório de gemas Ruby com grande sucesso. Está disponível no Debian / Ubuntu.
fonte
Eu tive uma situação semelhante, mas no meu caso o link simbólico deve apontar para um caminho relativo, então escrevi este script python para executar o truque:
Para cada linha de entrada (que é uma lista de arquivos), o script divide a lista de arquivos (separados por espaços em branco), obtém o caminho relativo de cada arquivo para o primeiro e cria o link simbólico.
fonte
Portanto, a resposta dada pelo arnefm (copiada em toda a Internet) não lida com espaços nos nomes dos arquivos. Eu escrevi um script que lida com espaços em arquivos.
O que isso faz é encontrar dupes e gravá-los PIPE separados em um arquivo chamado 'arquivos'.
Em seguida, ele lê o arquivo de volta, linha por linha, em uma matriz, e cada elemento da matriz é delimitado pelo PIPE.
Em seguida, itera sobre todos os elementos que não são o primeiro da matriz, substituindo o arquivo por um link simbólico para o primeiro elemento.
O arquivo externo ('arquivos') pode ser removido, se o comando fdupes for executado em um subshell, que é lido diretamente a qualquer momento, mas dessa maneira parece mais claro.
fonte
Algumas advertências na frente:
fdupes -1r common/base/dir | while read -r -a line ; do ln -sf $(realpath --relative-to ${line[1]} ${line[0]}) ${line[1]}; done
Se mais de 2 arquivos forem duplicados (por exemplo, arquivo1 arquivo2 arquivo3), precisamos criar um link simbólico para cada par - trate arquivo1, arquivo2 e arquivo1, arquivo3 como 2 casos separados:
Gastar isso para manipular automaticamente um número arbitrário de duplicatas por linha exigirá um pouco mais de esforço.
Outra abordagem seria criar primeiro links simbólicos para caminhos absolutos e depois convertê-los:
Isso é baseado na resposta de @Gilles: /unix//a/100955/77319
fonte