#NodeJS

Removendo arquivos duplicados do HD com node js

Vez ou outra nos deparamos com o tradicional problema de termos várias cópias dos mesmos arquivos espalhados pelo computador ocupando espaço no HD desnecessariamente, e mesmo hoje sendo bem mais barato termos grandes volumes pra armazenamento, isso pode se tornar um problema, principalmente considerando que o tamanho dos arquivos também cresceu bastante quando comparamos com alguns anos atrás. Se levarmos em consideração fotos, vídeos 4k etc, podemos perder alguns GB de arquivos.

Para resolver esse problema temos diversas ferramentas pagas e gratuitas para todos os SOs, como CCleaner , Clean My Mac X , Duplicate Cleaner , entre outros. Todas essas ferramentas possuem alguma função para remoção de arquivos duplicados entre diversas outras funções, mas caso você tenha alguma necessidade mais específica, ou basicamente não queira instalar nada e construir você mesmo a solução, é possível fazer um script que resolva esse problema de maneira bem simples.

Abaixo deixo um script que construi numa situação em que precisei varrer dois diretórios identificar arquivos iguais nos dois, e remover esses arquivos de um dos diretórios.

Dependências

O primeiro passo é instalar as dependências. Nesse script utilizei o Lodash e o Glob para facilitar a identificação da interseção entre os arquivos e o carregamento dos arquivos a partir de um padrão.

Bash
$ yarn add lodash glob

Carregando os arquivos para memória

A primeira parte do script consiste no carregamento dos arquivos para memória.

JavaScript
const glob = require('glob');

const INPUT1 = '/path/to/files1';
const INPUT2 = '/path/to/files2';

const filesMap1 = {};
const filesMap2 = {};

const files1 = glob.sync(`${INPUT1}/**/*.*`).map((filePath) => {
  const fileName = filePath.split('/').pop().toLowerCase();
  filesMap1[fileName] = filePath;

  return fileName;
});
const files2 = glob.sync(`${INPUT2}/**/*.*`).map((filePath) => {
  const fileName = filePath.split('/').pop().toLowerCase();
  filesMap2[fileName] = filePath;

  return fileName;
});

O trecho acima faz basicamente duas coisas, utiliza o glob pra varrer todos os arquivos nos paths dos diretórios informados, indexa o path completo de cada arquivo pelo nome usando um objeto, e guarda a lista com o nome dos arquivos em um array. Os arrays com os nomes do arquivos serão utilizados para identificar os arquivos duplicados e o índice com o caminho facilita na hora da remoção dos arquivos pois conseguimos, a partir do nome do arquivo a ser removido obter diretamente o path sem precisar varrer a lista inteira de novo.

Removendo os duplicados

A última parte do script consiste em usar as estruturas geradas na parte anterior para identificar os arquivos duplicados e removê-los.

JavaScript
const _ = require('lodash');
const fs = require('fs');

...

const intersection = _.intersection(files1, files2);

console.log(`Total files input 1: ${files1.length}`)
console.log(`Total files input 2: ${files2.length}`)
console.log(`Total files intersection: ${intersection.length}`)

intersection.forEach((file) => {
  const filePath = filesMap1[file];
  console.log(`File to delete: ${filePath}`);
  fs.rmSync(filePath);
});

Nessa parte a função intersection do lodash foi utilizada para facilitar a identificação dos arquivos duplicados. Ela basicamente é uma função que retorna a interseção entre duas listas, nesse caso, foram passados como parâmetros os dois arrays contendo as listas com os nomes dos arquivos de cada diretório de entrada, a inserseção entre essas duas listas resulta exatamente nos arquivos duplicados.

Uma vez tendo a lista com a interseção, basta passar por ela, buscar o path dos arquivos utilizando o índice criado na primeira parte do script, e removê-lo usando o módulo File System do Node .

Código completo

O código completo do script fica dessa forma:

JavaScript
const _ = require('lodash');
const fs = require('fs');
const glob = require('glob');

const INPUT1 = '/path/to/files1';
const INPUT2 = '/path/to/files2';

const filesMap1 = {};
const filesMap2 = {};

const files1 = glob.sync(`${INPUT1}/**/*.*`).map((filePath) => {
  const fileName = filePath.split('/').pop().toLowerCase();
  filesMap1[fileName] = filePath;

  return fileName;
});
const files2 = glob.sync(`${INPUT2}/**/*.*`).map((filePath) => {
  const fileName = filePath.split('/').pop().toLowerCase();
  filesMap2[fileName] = filePath;

  return fileName;
});

const intersection = _.intersection(files1, files2);

console.log(`Total files input 1: ${files1.length}`)
console.log(`Total files input 2: ${files2.length}`)
console.log(`Total files intersection: ${intersection.length}`)

intersection.forEach((file) => {
  const filePath = filesMap1[file];
  console.log(`File to delete: ${filePath}`);
  fs.rmSync(filePath);
});

É isso, com apenas poucas linhas de código é possível construir uma solução para o problema de remover arquivos duplicados, e entendendo o funcionamento de cada parte é possível adptar essa solução para situações específicas, como automatizar essa validação durante algum pipeline de outra aplicação em node, ou buscar apenas arquivos num padrão diferente, e por aí vai.

Qualquer dúvida ou sugestão, adicionem nos comentários por favor. Valeu demais!

Removendo arquivos duplicados do HD com node js

Como criar um aplicativo para Android

Removendo arquivos duplicados do HD com node js

O que é node js? Criando seu

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *