如何逐行组合`stat`和`md5sum`输出?

问题描述

统计部分:

$ 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 部分:

$ find * -depth -exec md5sum {} + |排序 -d > md5_file $ cat 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

解决方法

这实际上只是@Zilog80 解决方案的一个小改动。通过在 git bash 下在 Windows 笔记本电脑上运行的几百个文件的小数据集上跳过 read ,我的时间测试快了几秒钟。天啊。

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 存储库中工作并且宁愿跳过 {{1} } 树...),这是一个返工。


.git
,

最快的方法应该是:

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来逐个文件应用statmd5sum,然后我们读取两个输出行并使用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 之类的东西。