У меня есть сценарий оболочки, в котором мне нужно проверить, содержат ли два файла одинаковые данные или нет. Я делаю это для большого количества файлов, и в моем скрипте diff
команда кажется узким местом производительности.
Вот строка:
diff -q $dst $new > /dev/null
if ($status) then ...
Может ли быть более быстрый способ сравнения файлов, возможно, собственный алгоритм вместо стандартного diff
?
diff
иcmp
.Ответы:
Я считаю,
cmp
что остановится на первой разнице байтов:источник
cmp -s $old $new
тоже работает.-s
коротка для--silent
cmp
сначала проверит размер файла. Вот версия GNU, если вы хотите увидеть дополнительные оптимизации, которые она включает: git.savannah.gnu.org/cgit/diffutils.git/tree/src/cmp.cМне нравится @Alex Howansky для этого использовал cmp --silent. Но мне нужен как положительный, так и отрицательный ответ, поэтому я использую:
Затем я могу запустить это в терминале или с помощью ssh для проверки файлов на постоянный файл.
источник
echo success
команда (или любая другая команда, которую вы положили на ее место) терпит неудачу, будет запущена ваша команда «отрицательный ответ». Вы должны использовать конструкцию if-then-else-fi. Например, как этот простой пример .Почему вы не получаете хэш содержимого обоих файлов?
Попробуйте этот скрипт, назовите его, например, script.sh, а затем запустите его следующим образом: script.sh file1.txt file2.txt
источник
1/(2^511)
. Если вы не беспокоитесь о том, что кто-то намеренно пытается создать столкновение, идея этого метода, создающего ложное срабатывание, на самом деле не является серьезной проблемой.cmp
все еще более эффективен, так как он не должен читать весь файл в случае, если файлы не совпадают.Поскольку я отстой и у меня недостаточно очков репутации, я не могу добавить этот комментарий в качестве комментария.
Но, если вы собираетесь использовать
cmp
команду (и не хотите / не хотите быть многословным), вы можете просто получить статус выхода. Поcmp
справочной странице:Итак, вы можете сделать что-то вроде:
источник
cmp --silent $FILE1 $FILE2 ; if [ "$?" == "1" ]; then echo "files differ"; fi
который, в свою очередь, является более сложным,cmp --silent $FILE1 $FILE2 || echo "files differ"
поскольку вы можете напрямую использовать команду в выражении. Это заменяет$?
. В результате сравнивается существующий статус команды. И это то, что делает другой ответ. Кстати. Если с кем-то борются--silent
, это не везде поддерживается (busybox). использовать-s
Для файлов, которые не отличаются, любой метод потребует полностью прочитать оба файла, даже если чтение было в прошлом.
Альтернативы нет. Поэтому создание хэшей или контрольных сумм в определенный момент времени требует чтения всего файла. Большие файлы занимают время.
Извлечение метаданных файла происходит намного быстрее, чем чтение большого файла.
Итак, есть ли какие-нибудь метаданные файла, которые вы можете использовать, чтобы установить, что файлы разные? Размер файла ? или даже результаты команды file, которая просто читает небольшую часть файла?
Фрагмент кода примера размера файла:
Если файлы одинакового размера, вы застряли с полным чтением файлов.
источник
ls -n
чтобы избежать проблем, если имена пользователей или групп имеют пробелы.Попробуйте также использовать команду cksum:
Команда cksum выведет количество байтов файла. Смотрите "man cksum".
источник
md5
все равно считывает весь файл, поэтомуcmp
остановка на первом разнице будет намного быстрее.Проведя некоторое тестирование с Raspberry Pi 3B + (я использую файловую систему с наложением, и мне нужно периодически выполнять синхронизацию), я провел собственное сравнение для diff -q и cmp -s; обратите внимание, что это журнал из / dev / shm, поэтому скорость доступа к диску не проблема:
Я запускал его пару раз. У cmp -s было несколько меньше времени на тестовом боксе, который я использовал. Так что, если вы хотите использовать cmp -s для работы между двумя файлами ....
источник