什么是文件散列的足够文件信息?

时间:2014-04-25 17:11:13

标签: algorithm file hash

由于制作完整二进制文件的哈希值太大而无法在相当快的时间内进行计算:

散列文件的文件信息是什么?以下列出了理想情况下最终散列的属性:

  • 相对于目录中的其他文件无冲突
  • 捕获所有文件更改

根据经验,我们用来创建足够熵的信息越少越好。由于特定信息的检索速度很大程度上取决于给定的环境(OS,语言的文件IO,所用库的IO等),因此在此不应该忽略它。

(这是我在社区维基上的第一次尝试。我的理由是,这里提到的信息非常通用,但(希望)提供信息。我也希望将这个问题标记为社区维基,所以它可以在适合的地方得到改善。)

2 个答案:

答案 0 :(得分:1)

一般概述

我们的目标是在不使用冗余数据的情况下跟踪两个文件状态之间的差异。因此,每个信息源必须是文件状态信息的脱节子集。

以下各项代表有关文件的信息来源:

  • 文件名称
  • 相对于指定文档根目录的目录路径(也就是来自document-root的绝对路径)
  • 文件权限
  • 文件所有者(用户/组)
  • 最后更改时间
  • 文件大小
  • 文件所在机器的主机名
  • 实际保存的二进制数据

每件物品注意事项

档案名称

文件的名称是其绝对文件系统路径(最后一位)的一部分,正如@ La-comadreja所说,它的独特之处在于系统上没有两个文件可以具有相同的绝对路径。强烈建议使用File的名称与其绝对路径的其余部分(请参阅directory-path以获取更多信息)来避免与其他文件的哈希冲突。

目录路径

虽然文件绝对路径将是完全唯一的,但应注意在某些情况下散列绝对路径可能是不合适的。例如,当两个文件在两台机器上没有相同的绝对路径时,比较不同机器上两个文件的哈希很可能会失败。这在具有不同OS和/或架构的机器上变得更加成问题。因此,鼓励指定文档根并从中解析绝对路径。

权限

如果要跟踪对文件权限的更改,下面的测试表明您需要将它们直接包含在哈希中,因为它们不会更改有关该文件的任何其他信息(最明显的是时间戳)。但请注意,在不同的计算机上处​​理权限的方式完全不同,因此必须谨慎行事(例如,使用规范的权限转换方案)。

所有权

所有权,就像权限一样,在体系结构和文件系统之间的处理方式也大不相同。所有权变更不会改变其他信息(如下面的测试所示)。

时间戳

文件的时间戳也是在所有(或至少是最常见的)系统上不统一实现的。首先,我们可以看到的不同文件系统上有不同的时间戳:创建日期,修改日期,访问日期等。为了我们的目的,修改日期是最合适的,因为它受大多数可用文件系统的支持{{ 3}}并保存我们需要的确切信息:文件的最后一次更改。但是,比较不同操作系统中的文件可能会产生问题,因为Windows和Unix处理时间戳(通常)不同(请参阅此处[1]以获取有关该问题的详细文章)。请注意,无论何时编辑文件(忽略边缘情况),文件的修改日期都会更改,因此时间戳表示文件大小的更改(请注意,相反的情况不成立,请参阅文件大小)。

文件大小

文件大小(以字节为单位)非常好地指示文件是否已被编辑(权限,所有权和名称更改除外),因为每次编辑都会更改文件内容,从而更改其大小。但是,如果对文件的添加与删除完全一样大,则不适用。因此,文件时间戳可能是更好的指标。此外,计算文件二进制大小可能是计算密集型的。

主机名

如果想要跨多个主机比较文件并将不同主机上的相同文件视为不同,则该机器的主机名(或主机的另一个合适的唯一标识符)应包含在散列中。

二进制数据

当然,文件的二进制数据具有检查文件是否已更改的所有必要信息。但是,它也太资源密集,不具备任何实用性。我非常劝阻使用这些信息。

建议

以下来源用于比较文件:

  • 文件名称
  • 目录路径
  • 时间戳(见上文有关问题)

以下额外资源可用于跟踪更多信息:

  • 权限(见上文)
  • 所有权(见上文)
  • 主机名(在不同机器之间进行比较时)

以下信息来源应予以忽视:

  • 文件大小
  • 二进制数据

测试

我对Debian进行了一些测试,检查更改一个信息是否会改变另一个信息。最有趣的是,重命名权限更改所有者更改不会影响时间戳更改文件大小更改< / strong>即可。 (请注意,这些测试目前仅在Debian Linux上进行测试。其他操作系统的行为可能会有所不同。)

$ ls -l
-rw-r--r-- 1 alex alex 30 Apr 26 11:04 bar
-rw-r--r-- 1 alex alex  0 Apr 26 11:03 baz
-rw-r--r-- 1 alex alex 14 Apr 26 11:04 foo
$ mv baz baz2
$ ls -l
-rw-r--r-- 1 alex alex 30 Apr 26 11:04 bar
-rw-r--r-- 1 alex alex  0 Apr 26 11:03 baz2
-rw-r--r-- 1 alex alex 14 Apr 26 11:04 foo
$ chmod 777 foo
$ ls -l
-rw-r--r-- 1 alex alex 30 Apr 26 11:04 bar
-rw-r--r-- 1 alex alex  0 Apr 26 11:03 baz2
-rwxrwxrwx 1 alex alex 14 Apr 26 11:04 foo
$ mv baz2 baz
$ echo "Another string" >> bar
$ ls -l
-rw-r--r-- 1 alex alex 45 Apr 26 11:17 bar
-rw-r--r-- 1 alex alex  0 Apr 26 11:03 baz
-rwxrwxrwx 1 alex alex 14 Apr 26 11:04 foo
$ sudo chown root baz
$ ls -l
-rw-r--r-- 1 alex alex 45 Apr 26 11:17 bar
-rw-r--r-- 1 root alex  0 Apr 26 11:03 baz
-rwxrwxrwx 1 alex alex 14 Apr 26 11:04 foo

答案 1 :(得分:0)

假设所有文件都在同一台机器上,目录路径和文件名应该产生唯一的组合,因为同一目录中的两个文件不能具有相同的名称。上次更改的目录路径,文件名和时间戳应捕获每个更改。

如果文件位于不同的计算机上,则计算机名称应包含在目录路径中。