如何逐行组合 `stat` 和 `md5sum` 输出?
How to combine `stat` and `md5sum` output line by line?
统计部分:
$ find * -depth -exec stat --format '%n %U %G' {} + | sort -d > acl_file
$ cat acl_file
xfce4/desktop/icons screen0-3824x1033.rc john john
Code/CachedData/f30a9b73e8ffc278e71575118b6bf568f04587c8/index-ec362010a4d520491a88088c200c853d.code john john
VirtualBox/selectorwindow.log.6 john john
- md5sum部分:
$ 查找 * -depth -exec md5sum {} + |排序 -d > md5_file
$猫md5_file
3da180c2d9d1104a17db0749d527aa4b xfce4/desktop/icons screen0-3824x1033.rc
3de44d64a6ce81c63f9072c0517ed3b9 Code/CachedData/f30a9b73e8ffc278e71575118b6bf568f04587c8/index-ec362010a4d520491a88088c200c853d.code
3f85bb5b59bcd13b4fc63d5947e51294 VirtualBox/selectorwindow.log.6
如何将stat --format '%n %U %G'
和md5sum
合并并逐行输出到文件,如:
3da180c2d9d1104a17db0749d527aa4b xfce4/desktop/icons screen0-3824x1033.rc john john
3de44d64a6ce81c63f9072c0517ed3b9 Code/CachedData/f30a9b73e8ffc278e71575118b6bf568f04587c8/index-ec362010a4d520491a88088c200c853d.code john john
3f85bb5b59bcd13b4fc63d5947e51294 VirtualBox/selectorwindow.log.6 john john
最快的方法应该是:
find * -type f -exec stat --format '%n %U %G' "{}" \; -exec md5sum "{}" \; |
{ while read -r line1 && read -r line2; do printf "%s %s\n" "${line2/ */}" "${line1}";done; } |
sort -d
我们使用两个-exec
逐个文件应用stat
和md5sum
,然后我们读取两个输出行并使用printf
逐个文件格式化一个输出行stat
/md5sum
的输出。我们最终将整个输出通过管道传输到 sort
.
警告: 当我们通过管道对整个输出进行排序时,您可能会等待所有 stat/md5sum 完成后才能在控制台上获得任何输出。
如果只有 md5sum
而不是 stat
在文件上失败(反之亦然),输出将被丢弃。
编辑: 输出更安全的方法:
find * -type f -exec md5sum "{}" \; -exec stat --format '%n %U %G' "{}" \; |
{ while read -r line; do
mdsum="${line/[0-9a-f]* /}";
[ "${mdsum}" != "${line}" ] &&
{ mdsumdisp="${line% ${mdsum}}"; mdsumfile="${mdsum}"; } ||
{ [ "${line#${mdsumfile}}" != "${line}" ] &&
printf "%s %s\n" "${mdsumdisp}" "${line}"; };
done; } | sort -d
在这里,至少,我们检查我们在预期行上有类似 md5sum 的东西与行中的文件匹配。
这实际上只是@Zilog80 解决方案的一个小变体。我的时间测试通过在 git bash windows 笔记本电脑上的几百个文件 运行 的小型数据集上跳过 read
s 快了几秒钟. YMMV.
mapfile -t lst< <( find . -type f -exec md5sum "{}" \; -exec stat --format '%U %G' "{}" \; )
for ((i=0; i < ${#lst[@]}; i++)); do if (( i%2 )); then echo "${lst[i]}"; else printf "%s " "${lst[i]}"; fi done | sort -d
编辑
我原来的解决方案很糟糕。它会跳过隐藏子目录中的文件,并且 printf
会用空格破坏文件名。如果您没有要处理的隐藏目录,或者如果您 想要 跳过这些目录(例如,您正在 git
存储库中工作并且宁愿跳过 .git
树...),这里是返工。
shopt -s dotglob # check hidden files
shopt -s globstar # process at arbitrary depth
for f in **/*; do # this properly handles odd names
[[ -f "$f" ]] && echo "$(md5sum "$f") $(stat --format "%U %G" "$f")"
done | sort -d
统计部分:
$ find * -depth -exec stat --format '%n %U %G' {} + | sort -d > acl_file
$ cat acl_file
xfce4/desktop/icons screen0-3824x1033.rc john john
Code/CachedData/f30a9b73e8ffc278e71575118b6bf568f04587c8/index-ec362010a4d520491a88088c200c853d.code john john
VirtualBox/selectorwindow.log.6 john john
- md5sum部分:
$ 查找 * -depth -exec md5sum {} + |排序 -d > md5_file $猫md5_file
3da180c2d9d1104a17db0749d527aa4b xfce4/desktop/icons screen0-3824x1033.rc
3de44d64a6ce81c63f9072c0517ed3b9 Code/CachedData/f30a9b73e8ffc278e71575118b6bf568f04587c8/index-ec362010a4d520491a88088c200c853d.code
3f85bb5b59bcd13b4fc63d5947e51294 VirtualBox/selectorwindow.log.6
如何将stat --format '%n %U %G'
和md5sum
合并并逐行输出到文件,如:
3da180c2d9d1104a17db0749d527aa4b xfce4/desktop/icons screen0-3824x1033.rc john john
3de44d64a6ce81c63f9072c0517ed3b9 Code/CachedData/f30a9b73e8ffc278e71575118b6bf568f04587c8/index-ec362010a4d520491a88088c200c853d.code john john
3f85bb5b59bcd13b4fc63d5947e51294 VirtualBox/selectorwindow.log.6 john john
最快的方法应该是:
find * -type f -exec stat --format '%n %U %G' "{}" \; -exec md5sum "{}" \; |
{ while read -r line1 && read -r line2; do printf "%s %s\n" "${line2/ */}" "${line1}";done; } |
sort -d
我们使用两个-exec
逐个文件应用stat
和md5sum
,然后我们读取两个输出行并使用printf
逐个文件格式化一个输出行stat
/md5sum
的输出。我们最终将整个输出通过管道传输到 sort
.
警告: 当我们通过管道对整个输出进行排序时,您可能会等待所有 stat/md5sum 完成后才能在控制台上获得任何输出。
如果只有 md5sum
而不是 stat
在文件上失败(反之亦然),输出将被丢弃。
编辑: 输出更安全的方法:
find * -type f -exec md5sum "{}" \; -exec stat --format '%n %U %G' "{}" \; |
{ while read -r line; do
mdsum="${line/[0-9a-f]* /}";
[ "${mdsum}" != "${line}" ] &&
{ mdsumdisp="${line% ${mdsum}}"; mdsumfile="${mdsum}"; } ||
{ [ "${line#${mdsumfile}}" != "${line}" ] &&
printf "%s %s\n" "${mdsumdisp}" "${line}"; };
done; } | sort -d
在这里,至少,我们检查我们在预期行上有类似 md5sum 的东西与行中的文件匹配。
这实际上只是@Zilog80 解决方案的一个小变体。我的时间测试通过在 git bash windows 笔记本电脑上的几百个文件 运行 的小型数据集上跳过 read
s 快了几秒钟. YMMV.
mapfile -t lst< <( find . -type f -exec md5sum "{}" \; -exec stat --format '%U %G' "{}" \; )
for ((i=0; i < ${#lst[@]}; i++)); do if (( i%2 )); then echo "${lst[i]}"; else printf "%s " "${lst[i]}"; fi done | sort -d
编辑
我原来的解决方案很糟糕。它会跳过隐藏子目录中的文件,并且 printf
会用空格破坏文件名。如果您没有要处理的隐藏目录,或者如果您 想要 跳过这些目录(例如,您正在 git
存储库中工作并且宁愿跳过 .git
树...),这里是返工。
shopt -s dotglob # check hidden files
shopt -s globstar # process at arbitrary depth
for f in **/*; do # this properly handles odd names
[[ -f "$f" ]] && echo "$(md5sum "$f") $(stat --format "%U %G" "$f")"
done | sort -d