Сравните 2 папки и найдите файлы с разным количеством байтов

Используя Gnome в Linux Mint 12, я скопировал папку размером около 9,7 ГБ (содержащую сложное дерево подпапок) с одного флэш-диска NTFS на другой флэш-накопитель NTFS. Согласно Gnome, файл подсчитывает совпадение, но согласно du (и другим программам) количество байтов не совпадает. (У меня была такая же проблема с копированием папок в других дистрибутивах Linux и Windows XP.)

Я только хочу знать, какие файлы не имеют совпадающих байтов. (Я не хочу сравнивать содержимое каждого файла, потому что это займет слишком много времени.) Какой самый лучший, самый простой и быстрый способ найти файлы с несоответствующим байтом?

Ответ 1

Я бы адаптировал ответ по @user1464130, так как у него проблемы с обработкой пробелов в именах файлов.

cd dir1
find . -type f -printf "%p %s\n" | sort > ~/dir1.txt
cd dir2
find . -type f -printf "%p %s\n" | sort > ~/dir2.txt
diff ~/dir1.txt ~/dir2.txt

Если вы хотите запустить команду для каждого файла и использовать результат в отчете, вы можете использовать конструкцию while Bash. В этом примере md5sum используется для вычисления контрольной суммы для каждого файла.

find . -maxdepth 1 -type f -printf "%p %s\n" | while read path size; do echo "$path - $(md5sum $path | tr -s " " | cut -f 1 -d " ") - $size" ; done

Каждый $() выполняется отдельно и позволяет нам вычислить контрольную сумму для каждого файла. Использование tr сжимает все последовательные пробелы в один пробел и cut извлечение слова в n-й позиции, здесь в первой позиции. Если мы этого не сделаем, мы получим имя файла два раза, потому что md5sum вернет его на стандартный вывод.

Вот пример без использования сравнения (без diff). Обратите внимание, что я использовал тире - для выделения трех данных, которые мы выводим для каждого файла, но это может быть проблемой, если вы хотите передать его в другую программу.

$ find . -maxdepth 1 -name "*.c" -type f -printf "%p %s\n" |  while read path size; do echo "$path - $(md5sum $path | tr -s " " | cut -f 1 -d " ") - $size" ; done
./thread.c - 5f2b7b12c7cd12fcb9e9796078e5d15b - 584
./utils.c - d61bc1dbc72768e622a04f03e3b8f7a2 - 3413

РЕДАКТИРОВАТЬ: И для обработки пробелов в именах файлов и по-прежнему получить контрольную сумму и размер, вы можете использовать следующий код.

$ find . -maxdepth 1 -name "*.c" -type f -print0 | xargs -0 -n 1 md5sum | while read checksum path; do echo $path $(stat --printf="%s" "$path") $checksum ; done
./ini tia li za tion.c 84 31626123e9056bac2e96b472bd62f309

Ответ 2

Вы проверяли, имеют ли оба раздела одинаковые атрибуты? (размер блока, размер, зарезервированное пространство для удаления или плохие блоки и т.д.)

В вашем конкретном случае я бы рекомендовал rsync с опцией -n (или --dry-run). Он расскажет вам, какие файлы разные. То есть:

$ rsync -I -n /source/ /target/

Опция -I - игнорировать времена. Вы можете использовать ту же команду, чтобы сделать обе каталоги эквивалентными (временная метка, разрешения и т.д.).

Проверьте руководство по rsync или попробуйте параметр --help, чтобы получить больше опций и примеры того, как его использовать. Это очень мощный.

Ответ 3

Предполагая, что вам нужно сравнить dir1 и dir 2, вот консольные команды:

cd dir1
find . -type f|sort|xargs ls -l| awk '{print $5,$8}' > ~/dir1.txt
cd dir2
find . -type f|sort|xargs ls -l| awk '{print $5,$8}' > ~/dir2.txt
diff ~/dir1.txt ~/dir2.txt

Вам может потребоваться отредактировать параметры awk, чтобы правильно отредактировать длину и путь к файлу.