查找 | xargs shasum 创建校验和文件本身的校验和(过早地)并在检查时失败

use*_*391 10 find xargs hashsum checksum

我的问题(在带有 的脚本中#!/bin/sh)如下:为了存档目的,我尝试对目录中的所有文件进行校验和。具有所有文件名的校验和(在我的情况下为 sha1)文件应位于同一目录中。假设我们有一个~/test包含文件f1f2:的目录。

mkdir ~/test
cd ~/test
echo "hello" > f1
echo "world" > f2
Run Code Online (Sandbox Code Playgroud)

现在计算校验和

find -maxdepth 1 -type f -printf '%P\n' | xargs shasum
Run Code Online (Sandbox Code Playgroud)

正是我想要的,它只列出当前目录的所有文件并计算 sha1 总和(maxdepth 可能会在以后更改)。STDOUT 上的输出是:

f572d396fae9206628714fb2ce00f72e94f2258f  f1
9591818c07e900db7e1e0bc4b884c945e6a61b24  f2
Run Code Online (Sandbox Code Playgroud)

不幸的是,当尝试将其保存到文件时

find -maxdepth 1 -type f -printf '%P\n' | xargs shasum > sums.sha1
Run Code Online (Sandbox Code Playgroud)

生成的文件显示自身的校验和:

da39a3ee5e6b4b0d3255bfef95601890afd80709  sums.sha1
f572d396fae9206628714fb2ce00f72e94f2258f  f1
9591818c07e900db7e1e0bc4b884c945e6a61b24  f2  
Run Code Online (Sandbox Code Playgroud)

因此在稍后失败shasum --check,因为在保存最后一个总和时附加文件修改的明显问题。

我环顾四周,通过使用-p标志 for xargs,我发现它甚至在执行 find 命令之前以某种方式创建了输出文件,因此找到了附加文件并将进行校验......

我知道作为一种解决方法,我可以将校验和保存到另一个位置(通过 临时目录mktemp)或专门在 find 中排除它,但我想了解为什么它的行为方式如此 - 在我看来这不是那么有用,例如,如果第一个命令会检查输出文件是否已经在磁盘上,它永远不会得到正确的答案......

Ant*_*hon 12

您可以xargs使用以下方法阻止文件到达:

find . -maxdepth 1 -type f ! -name sums.sha1 -printf '%P\n' |
  xargs -r shasum -- > sums.sha1
Run Code Online (Sandbox Code Playgroud)

但是,为了防止文件名出现空格、换行符、引号或反斜杠的问题,我会使用:

find . -maxdepth 1 -type f ! -name sums.sha1 -printf '%P\0' |
  xargs -r0 shasum -- > sums.sha1
Run Code Online (Sandbox Code Playgroud)

反而。

--是为了避免以-. 然而,它对名为-. 如果您使用了-print0代替-printf '%P\0',您就不需要--并且文件也不会出现问题-


ter*_*don 7

由于您正在使用-maxdepth 1,我假设您不想要递归。如果是这样,只需在 shell 中执行此操作:

for f in ~/test/*; do
    shasum -- "$f"
done > sums.sha1
Run Code Online (Sandbox Code Playgroud)

要跳过目录,您可以执行以下操作:

for f in ~/test/*; do
    [ ! -d "$f" ] && shasum -- "$f"
done > sums.sha1
Run Code Online (Sandbox Code Playgroud)

如果您确实需要递归并且正在使用bash,请执行以下操作:

shopt -s globstar
for f in ~/test/**; do
    [ ! -d "$f" ] && shasum -- "$f"
done > sums.sha1
Run Code Online (Sandbox Code Playgroud)

请注意,所有这些方法都可以处理任意文件名,包括带有空格、换行符或其他任何内容的文件名。