find 配合 sha256sum 时如何排除哈希输出文件?
数据阿明
在 find 中加入 ! -name 'hashedoutput.sha256',就能排除输出文件。Shell 会在启动 find 前处理 > 重定向,创建输出文件或清空已有文件,因此 find 扫描目录时会看到它。
修改函数
gen_sha256sum () {
find "$1" -maxdepth 1 -type f \
! -name 'hashedoutput.sha256' \
-exec sha256sum {} + > "$1/hashedoutput.sha256"
}
调用时传入需要处理的目录:
gen_sha256sum /path/to/files
各条件的作用是:
-maxdepth 1:只检查指定目录及其直接子项,不进入子目录。-type f:只处理普通文件。! -name 'hashedoutput.sha256':排除名为hashedoutput.sha256的文件。-exec sha256sum {} +:将匹配的文件分批作为参数交给sha256sum计算。
函数只处理一层目录,按固定文件名排除即可满足需求。
为什么输出文件会成为输入
虽然重定向写在原命令末尾,Shell 也会在 find 执行前打开输出文件。处理顺序是:
- 打开
$1/hashedoutput.sha256,如果文件不存在就创建,存在则截断为空文件。 - 启动
find,并将其标准输出连接到该文件。 find扫描$1,发现hashedoutput.sha256也符合-type f,便把它传给sha256sum。
因此,即使第一次运行前没有这个文件,也可能出现同样的问题。提前删除输出文件也无济于事,因为重定向会在扫描前重新创建它。
使用时需要注意什么
不要依赖文件遍历顺序来避开输出文件。如果文件在写入时又被读取,算出的哈希值无法代表最终生成的完整清单,应明确将它排除。
把 > 换成 >> 也不能解决问题。追加重定向同样会提前打开或创建输出文件,还会保留旧内容,使清单不断累积。
保留原来的 -exec ... {} + 写法即可,无需把文件名拼接成字符串再交给 Shell 执行。这种传参方式可以正确处理包含空格等字符的文件名。
题目标题提到了 openssl,但给出的函数调用的是 sha256sum。问题来自 Shell 重定向和 find 的筛选条件,无需改用 openssl。
备注:内容仅供参考。
