Определите, был ли файл изменен


10

В Linux (в настоящее время используется файловая система ext4), как можно быстро проверить, было ли изменено содержимое файла, не читая его содержимого?

Является ли statкоманда рекомендуемым подходом? Я сейчас делаю

$ stat --format "%Y" hello.txt

и позже я могу проверить, дает ли та же команда тот же вывод. Если это так, я делаю вывод, что hello.txt не изменился.

Я чувствую, что хочется добавить больше параметров, чтобы быть еще более уверенным. Например, добавит ли размер файла, имя файла и т. Д. Еще лучший «отпечаток» файла?

По этой теме я вспоминаю, что том TrueCrypt, который я когда-то имел, всегда игнорировался моей программой инкрементного резервного копирования, возможно потому, что TrueCrypt следил за тем, чтобы не оставлять никаких изменений метаданных. Я полагаю, что действительно возможно изменить все данные, возвращаемые stat, следовательно, не может быть гарантировано, что он подхватит все возможные модификации файла?


md5sum filename?
Рамеш

md5sumили любой вид контрольной суммы читает содержимое файла. Я не хочу этого делать, потому что это слишком медленно для моих целей.
DustByte

ls -tотсортирует содержимое в каталоге по времени модификации.
ryekayo

"был изменен"? Каждый файл был изменен, вопрос в том, когда он был изменен. Вы можете использовать «поиск» для поиска определенного диапазона времени модификации.
Рэй Эндрюс

Ответы:


5

Если вы хотите определить, был ли файл изменен обычным способом (редактирование его в каком-либо приложении, извлечение новой версии из систем контроля версий, перестройка и т. Д.), Проверьте, изменилось ли время его модификации (mtime) с последняя проверка. Вот что stat -c %Yсообщает.

Время модификации может быть установлено touchкомандой. Если вы хотите определить, был ли файл каким-либо образом изменен (включая использование touch, извлечение архива и т. Д.), Проверьте, изменилось ли время его изменения inode ( ctime ) с момента последней проверки. Вот что stat -c %Zсообщает. Ctime не может быть подделано, кроме как системным администратором (и даже тогда, только косвенными способами: путем изменения системных часов или путем прямого доступа к диску, минуя файловую систему).


Спасибо, я понимаю, что ctime - это то, что я должен использовать. Из моего вопроса не вытекало, что целью этого является использование его в моем собственном скрипте резервного копирования, где контрольные суммы будут вычисляться только для новых файлов или файлов, которые изменились. Я могу позволить себе вычисление контрольных сумм для файлов, которые изменились лишь «незначительно», скажем, изменились разрешения и т. Д. Я предпочитаю быть как можно ближе к реальному просмотру содержимого файла, чтобы определить изменение.
DustByte

3

Команда stat имеет разрешение всего в секунду. Таким образом, если файл был изменен дважды в одну и ту же секунду, вы можете пропустить изменение. Более новые файловые системы, такие как ext4, предоставляют метки времени с более высоким разрешением в наносекундах, но некоторые из старых инструментов еще не догнали.

Кроме того, другие программы могут устанавливать произвольное время изменения. Вы можете увидеть, как это может произойти с помощью сенсорной команды.

Если вас беспокоит какая-либо из этих двух возможностей, было бы неплохо взглянуть и на размер файла. Это то, что делает rsync, когда ищет измененные файлы.


1

Я чувствую, что хочется добавить больше параметров, чтобы быть еще более уверенным.

То, что у вас есть, это правильный метод. Единственная причина для этого может быть, если файловая система не обновляется должным образом - в этом случае вы столкнетесь с целой кучей более серьезных проблем.

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


0

Я делаю отпечаток пальца более подробно.

Я сделал небольшую функцию-обертку, которая генерирует одинаковый вывод для версий MacOS / BSD и GNU stat(также обнаруживает версию, установленную Homebrew с gпрефиксом).

init() {
  if command -v gstat > /dev/null; then
    # GNU coreutils with g prefix.
    statCmdArgs=("gstat" "--format=%n %s %b %u %g %i %h %Y %Z %W %o");
  elif ! stat --version > /dev/null 2> /dev/null; then
    # MacOS/BSD stat
    statCmdArgs=("stat" "-f" "%N %z %b %u %g %i %l %m %c %B %k");
  else
    # Assume GNU version without prefix.
    statCmdArgs=("stat" "--format=%n %s %b %u %g %i %h %Y %Z %W %o");
  fi;
}

getFileStatus() {
  "${statCmdArgs[@]}" "$1";
}

initФункция вызывается один раз во время инициализации скрипта и getFileStatusможет быть вызвана повторно без накладных обнаружения.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.