Моя проблема (в сценарии с #!/bin/sh
) заключается в следующем: я пытаюсь контрольную сумму всех файлов в каталоге для архивных целей. Файл контрольной суммы (в моем случае sha1) со всеми именами файлов должен находиться в одном каталоге. Допустим, у нас есть каталог ~/test
с файлами f1
и f2
:.
mkdir ~/test
cd ~/test
echo "hello" > f1
echo "world" > f2
Теперь вычисление контрольных сумм с
find -maxdepth 1 -type f -printf '%P\n' | xargs shasum
делает именно то, что я хочу, он перечисляет все файлы только текущего каталога и вычисляет суммы sha1 (maxdepth может быть изменен позже). Выход на STDOUT:
f572d396fae9206628714fb2ce00f72e94f2258f f1
9591818c07e900db7e1e0bc4b884c945e6a61b24 f2
К сожалению, при попытке сохранить это в файл с
find -maxdepth 1 -type f -printf '%P\n' | xargs shasum > sums.sha1
результирующий файл отображает контрольную сумму для себя:
da39a3ee5e6b4b0d3255bfef95601890afd80709 sums.sha1
f572d396fae9206628714fb2ce00f72e94f2258f f1
9591818c07e900db7e1e0bc4b884c945e6a61b24 f2
и, следовательно, не удается позже shasum --check
, из-за очевидной проблемы дополнительной модификации файла при сохранении последней суммы.
Я огляделся и, используя -p
флаг for xargs
, обнаружил, что он каким-то образом создает выходной файл еще до выполнения команды find, поэтому дополнительный файл найден и будет проверен ...
Я знаю, что в качестве обходного пути я мог бы сохранить контрольную сумму в другом месте (через временный каталог mktemp
) или исключить ее из функции find, но я хотел бы понять, почему она ведет себя так, как она работает - что, на мой взгляд, не очень полезно, например, если первая команда проверит, находится ли выходной файл на диске, она никогда не получит правильный ответ ...
sh
вызовов. Обратите внимание, что вам нужен аргумент для $0
ранее {}
.
tee
исчез? Я попробовал, и он работает нормально, я также подавил STDOUT с добавлением 1>/dev/null
. Было ли что-то не так с ответом или это ошибка?
xargs
, именно сама оболочка создает этот файл, потому что перед выполнением любой команды оболочка перенаправляет все входные, выходные и конвейерные данные, так что приfind
запуске выходной файл уже существует. Используйте-exec
вместо:find -maxdepth 1 -type f -exec sh -c 'shasum "$@" > sums.sha1' {} +