为什么更改文件名不会更改其校验和?

Ami*_*ahi 10 filesystems checksum

据我所知,即使更改一点文件,也会更改整个校验和结果,但是当我更改文件名时,这不会影响其校验和(我尝试过 SHA-1、SHA-256 和 MD5)。

为什么?文件名不是文件数据的一部分?它依赖于文件系统吗?

Kus*_*nda 41

文件的名称是目录条目中的字符串,并且许多其他元数据(文件类型、权限、所有权、时间戳等)存储在 inode 中。因此,文件名不是构成文件实际数据的一部分。事实上,单个文件在文件系统中可能有任意数量的名称(硬链接),并且还可以通过任意数量的任意命名的符号链接访问。

由于文件名不是文件数据的一部分,因此当您使用md5md5sum或某些类似实用程序计算例如 MD5 校验和时,它不会自动包含在内。

因此,更改文件的名称(或所有权、时间戳或权限等)或通过其其他名称或符号链接之一访问它(如果有),不会对文件的 MD5 校验和产生任何影响。

  • 类型/权限/所有权/时间戳等属于文件(inode)而不是任何目录中引用它的条目。该目录是一个包含 `name <-> inode` 条目的表。如今,文件的 *type* 经常被复制到目录条目中,因为它用于加快查找速度,但通常不会复制文件的其余部分元数据。还要注意,在任意数量的目录中,同一个文件可以有任意数量的条目。在所有目录中复制所有这些信息将是一种浪费。 (8认同)

ctr*_*lor 10

是的,正如您所说的“文件名不是文件数据的一部分”

文件名不能存储文件中。如果是,那么它将更改文件。然而,对文件名、其他元数据和文件数据进行校验和可能是有效的,但这通常是一个坏主意。

文件名是其包含目录的一部分。不是文件的一部分。

如果你想校验和/散列两者,那么像这样的事情会起作用

(可能不是一个好主意)

echo "$filename" | xargs -n1 -I{} bash -c 'echo "$1"; cat "$1"' x {} | shasum

  • 一个文件可以同时有多个不同的名称。名称在技术上是一个硬链接。你可以使用 `ln` 创建更多的硬链接,只要它在同一个文件系统上。如果添加第二个硬链接,则它有两个名称,它们都同样真实。 (10认同)
  • 如果您将文件名存储在文件中(而不是目录中),那么执行类似简单的 ls 操作将需要打开并读取每个文件。 (3认同)

ilk*_*chu 10

当我更改文件名时,这不会影响其校验和(我尝试过 SHA-1、SHA-256 和 MD5)。

嗯,这有点虚假的联系。SHA-1、SHA-256 和 MD5 不计算文件或文件名的哈希值,它们计算比特流的哈希值。所以,你得到的结果完全取决于你选择提供什么作为输入,而你没有表现出来。

现在,您可能使用了sha1sum,sha256summd5sum实用程序,实际上它们只在要散列的数据中包含给定文件的内容。不是文件名,不是权限位、所有者信息、时间戳或其他元数据。

不过,这并不具有进行这样做。这是两个文件及其名称的 SHA-256 哈希值:

$ echo hello > a.txt; cp a.txt b.txt
$ ./checksum.sh a.txt  b.txt 
aed49f7730ca0736fe1a021375d1ca9b509a4e72910b422578df8b4b1930aeca  -
bad46702033923726add35ef8d97570f1aa40d93dad1d6ba63e7b051a34b9efc  -
Run Code Online (Sandbox Code Playgroud)

该脚本只是将文件名添加到散列数据中。另一个应用程序可以在散列输入中包含元数据以及文件内容,或者包含仅覆盖部分数据的散列。

显然,包含文件名的缺点是即使是同一个文件也可能被不同的名称引用,因此可能有许多不同的哈希值:

/tmp/test$ ./checksum.sh a.txt ./a.txt /tmp/test/a.txt 
aed49f7730ca0736fe1a021375d1ca9b509a4e72910b422578df8b4b1930aeca  -
85ec58226886f4f853212b2d21bb2fb72447813ac13a59e9376b2e0c02074839  -
25c1c072481131e07c3fc20d16109472872233f658f4df3c4982fb195a048b96  -
Run Code Online (Sandbox Code Playgroud)

在等式中添加时间戳、所有者等几乎可以保证在将文件复制到另一个系统后散列是不同的,这使得散列的有用性相当可疑。甚至文件名也可能丢失或更改。

如果您想将元数据包含在散列中,最简单的方法可能是将文件放入 tar 存档或其他存储您认为有用的元数据的容器中,然后进行散列和复制。从存档中提取文件(内容)后,文件系统上的元数据可能不同,但您仍然可以验证文件来自哪个存档。


上面的脚本是:

$ cat checksum.sh
#!/bin/bash
for f in "$@"; do
        (printf "%s\0" "$f" ; cat "$f") | sha256sum - 
done
Run Code Online (Sandbox Code Playgroud)