| 
 | 1 | +#!/usr/bin/env bash  | 
 | 2 | +# Encuentra archivos duplicados por hash (md5) y lista sus rutas.  | 
 | 3 | +# Uso:  | 
 | 4 | +#  ./find_duplicates.sh --check    # solo informa  | 
 | 5 | +#  ./find_duplicates.sh --delete   # elimina duplicados dejando uno por hash (SÓLO USAR CON CAUTELA)  | 
 | 6 | +#  | 
 | 7 | +# Excluye node_modules, .git y venv por defecto.  | 
 | 8 | + | 
 | 9 | +set -euo pipefail  | 
 | 10 | + | 
 | 11 | +MODE="${1:---check}"  | 
 | 12 | +ROOT_DIR="${2:-.}"  | 
 | 13 | + | 
 | 14 | +TMPFILE=$(mktemp)  | 
 | 15 | +trap 'rm -f "$TMPFILE"' EXIT  | 
 | 16 | + | 
 | 17 | +echo "Generando hashes en $ROOT_DIR ..."  | 
 | 18 | +find "$ROOT_DIR" -type f \  | 
 | 19 | +  ! -path "*/node_modules/*" \  | 
 | 20 | +  ! -path "*/.git/*" \  | 
 | 21 | +  ! -path "*/venv/*" \  | 
 | 22 | +  ! -path "*/.venv/*" \  | 
 | 23 | +  -print0 |  | 
 | 24 | +  xargs -0 md5sum > "$TMPFILE"  | 
 | 25 | + | 
 | 26 | +echo "Buscando duplicados..."  | 
 | 27 | +awk '{ print $1 " " $2 }' "$TMPFILE" | sort | awk '  | 
 | 28 | +{  | 
 | 29 | +  hash=$1; $1=""; path=substr($0,2);  | 
 | 30 | +  a[hash]=a[hash] "||" path;  | 
 | 31 | +  cnt[hash]++;  | 
 | 32 | +}  | 
 | 33 | +END {  | 
 | 34 | +  for (h in cnt) {  | 
 | 35 | +    if (cnt[h] > 1) {  | 
 | 36 | +      n = split(a[h], arr, "||");  | 
 | 37 | +      printf("DUP_HASH %s COUNT %d\n", h, cnt[h]);  | 
 | 38 | +      for (i=1;i<=n;i++) if (length(arr[i])>0) print "  " arr[i];  | 
 | 39 | +      print "";  | 
 | 40 | +    }  | 
 | 41 | +  }  | 
 | 42 | +}  | 
 | 43 | +'  | 
 | 44 | + | 
 | 45 | +if [ "$MODE" = "--delete" ]; then  | 
 | 46 | +  echo "MODO --delete: eliminando duplicados y conservando el primer archivo listado por hash."  | 
 | 47 | +  awk '{ print $1 " " $2 }' "$TMPFILE" | sort | awk '  | 
 | 48 | +{  | 
 | 49 | +  hash=$1; $1=""; path=substr($0,2);  | 
 | 50 | +  if (!(hash in seen)) {  | 
 | 51 | +    seen[hash]=path;  | 
 | 52 | +  } else {  | 
 | 53 | +    print path;  | 
 | 54 | +  }  | 
 | 55 | +}' | while read -r dup; do  | 
 | 56 | +    echo "Eliminando: $dup"  | 
 | 57 | +    rm -v "$dup"  | 
 | 58 | +  done  | 
 | 59 | +  echo "Eliminación completada. Recomendado: revisar git status y confirmar."  | 
 | 60 | +else  | 
 | 61 | +  echo "Modo de solo verificación (--check). Para eliminar duplicados ejecutar con --delete."  | 
 | 62 | +fi  | 
0 commit comments