Удаление дубликатов файлов по хэшу#!/bin/bash
# -------------------------------------------
# Скрипт проходит по всем файлам в указанной
# директории, вычисляет их хэши и удаляет
# дубликаты (спрашивая подтверждение).
# -------------------------------------------
# Директория для сканирования.
# Если пользователь не передал путь, используется текущая.
dir="${1:-.}"
# Хэш-алгоритм. Можно заменить на:
# md5sum — быстрее, но менее надёжно
# sha1sum — средне
# sha256sum — медленнее, но максимально надёжно
algo="sha256sum"
# Ассоциативный массив "хэш → путь к оригиналу".
# В нём сохраняются хэши всех уже встреченных файлов.
declare -A seen
echo "-------------------------------------------"
echo " Сканирование директории: $dir"
echo " Алгоритм хеширования: $algo"
echo "-------------------------------------------"
echo
# Используем find для обхода ВСЕХ файлов.
# -type f — только обычные файлы.
# -print0 — вывод с нулевым разделителем, чтобы корректно
# обрабатывать имена с пробелами и спецсимволами.
while IFS= read -r -d '' file; do
# Вычисляем хэш файла. Команда вида:
# sha256sum file | awk '{print $1}'
# выводит только сам хэш без имени.
hash=$($algo "$file" | awk '{print $1}')
# Если этот хэш уже есть в массиве,
# значит, файл-дубликат найден.
if [[ ${seen[$hash]} ]]; then
echo " Найден дубликат:"
echo " Оригинал: ${seen[$hash]}"
echo " Дубликат: $file"
echo
# Запрашиваем подтверждение удаления.
read -p "Удалить дубликат? [y/N]: " answer
# Удаление только если ответ 'y' или 'Y'
if [[ "$answer" =~ ^[Yy]$ ]]; then
rm -v "$file" # -v — verbose, показывает что удалено
else
echo "Пропуск."
fi
echo
else
# Если хэша нет — запоминаем файл как оригинал.
seen[$hash]="$file"
fi
# Этот синтаксис < <(...) позволяет передавать результат find
# прямо в цикл while (без создания временных файлов).
done < <(find "$dir" -type f -print0)
echo "Готово!"
4.18K views12:01