如何为新文件创建 md5sum

How to create md5sum for new files

我们在我爸爸的电脑上创建了一个文件夹,供全家人存放和分享他们的照片和视频。

Example of directories:
/Family_Photo/Penguins/2017 09 02/
/Family_Photo/East Beach/2017 10 11/Seaside/
/Family_Photo/East Beach/2017 10 11/Games/

使用 md5deep,我能够为所有子目录中的所有文件创建一个完整的校验和列表

md5deep -r /Family_Photo/ > /Family_Photo/md5sum.log

而不是每次都为所有(新添加的和现有的)文件重新生成完整的 md5 校验和,

我如何创建一个 bash 脚本来自动检测任何之前没有被 md5 的文件并为这些新文件生成校验和并将它们附加到原始 md5sum.log

我将使用 ls -l(并将其存储在临时文件中),
然后在 Daily 上用一个新的 ls 来区分它?基础,如果 diff returns 0 一切都很好,如果 diff 显示差异。
然后我将仅 md5 由 diff 报告的文件,用新的 ls 更新 ls 临时文件。我将使用 --LTYPE-line-format=%< 这样它就不会查找已删除的文件(文件存在于临时文件中但不存在于 fresh-运行 ls 中)。

这将是查找 'new' 个文件的前提代码:

new_files=diff --suppress-common-lines --changed-group-format='%<' --unchanged-group-format='' temp_file $(ls -l)

deleted_files=diff --suppress-common-lines --changed-group-format='%>' --unchanged-group-format='' temp_file $(ls -l) #so you can log deletions too

我离开去写其他代码(首先制作临时文件并对数据进行哈希处理)

显然,如果您有一个目录,您必须 运行 ls -R 而不是 运行 您要检查的路径根目录中的脚本

解决方案

这应该可以解决问题:

comm -1 -3 <(grep --text --perl-regex --only-matching '(?<= ).+' /Family_Photo/md5sum.log | sort) <(find /Family_Photo -type f | sort) | xargs --delimiter='\n' --no-run-if-empty md5deep | tee -a /Family_Photo/md5sum.log

备注

  • 如果您使用与示例中不同的路径,请确保使用绝对规范路径 将选项 -exec realpath {} \; 附加到 find, 因为 md5deep 似乎将这样的路径写入文件,我们需要它们相同才能进行比较。
  • 此命令行使用 bash 特定语法(将命令作为文件传递),可能无法在不同的 shell 解释器中工作。

说明

  • comm -1 -3
    • 在这种特定情况下,我们使用此命令通过将找到的文件与现有列表进行比较来查看哪些文件是新文件。
    • comm 比较两个排序列表并输出哪些行对每个列表是唯一的,哪些行对两个列表都是相同的
    • -1 表示:不显示第一个列表独有的行
    • -3 表示:不显示两个文件共有的行[​​=115=]
    • 因此我们只输出第二个列表特有的行
  • <(grep --text --perl-regex --only-matching '(?<= ).+' /Family_Photo/md5sum.log | sort) 作为 comm 的第一个文件,我们传递了一个已经散列的文件名列表。
    • <(...) 是 bash 将程序结果作为文件参数传递的语法
    • 使用grep,我们通过匹配double-space
    • 后的任何内容从现有文件中提取文件名
    • --text 确保 md5sum.log 始终被视为文本文件而不被跳过
    • --perl-regex 使用 perl 正则表达式语法(我们需要它进行后视匹配)
    • --only-matching 只输出与模式匹配的文本,而不是匹配的整行
    • '(?<= ).+' 匹配模式:(?<= ) "look-behind" 模式,检查匹配前面是否有 </code> (两个 spaces );后跟 <code>.+(任意字符,一个或多个)
    • | sort 我们将 grep 的输出传递给 sort,因为 comm 需要排序列表
  • <(find /Family_Photo -type f | sort) 作为 comm 的第二个文件,我们传递找到的所有文件
    • <(...) 是 bash 将程序结果作为文件传递的语法
    • find 将递归给定目录并打印出所有文件名
    • -type -f 指示 find 只输出找到的文件名,不输出目录
    • | sort 我们将 grep 的输出传递给 sort,因为 comm 需要排序列表
  • | xargs --delimiter='\n' --no-run-if-empty md5deep 生成的新文件列表传递给 md5deep
    • |comm 的输出连接到 xargs
    • 的输入
    • xargs 将调用命令(在本例中为 md5deep),将输入的任何内容作为参数
    • --delimiter='\n'指定一个新行作为分隔符,这样文件名中的其他白色space就不会被误认为是新参数
    • --no-run-if-empty 如果我们没有要传递给它的新文件名,我们不想 运行 md5deep
  • | tee --append /Family_Photo/md5sum.log 生成的列表哈希将写入哈希文件
    • 这会显示新的 files/hashes 以方便您编写它们,如果您不想看到它们,只需使用 >> /Family_Photo/md5sum.log 即可。
    • |md5deep 的输出连接到 tee
    • 的输入
    • tee 将输出其输入并将其写入文件
    • --append 告诉 tee 不要覆盖文件内容,而是附加

感谢大家的投入。经过一番折腾,我想出了一些满足我当前需求的东西。

这部分是运行第一次

md5deep -r /Family_Photos/ > /Family_Photo/photos.md5
cd Family_Photos/ & find . -print | sort > today.txt

下一部分将构成我的脚本。 为每个 运行.

准备 txt 文件
cd Family_Photos/ & rm old.txt & mv today.txt old.txt

递归列出所有文件到today.txt

find . -print | sort > today.txt

将新添加的文件更新为new.txt

grep -xvFf old.txt today.txt > new.txt

生成所有新文件的 md5sum 并附加到 photos.md5

cat new.txt | xargs -d '\n' md5sum >> photos.md5