検索| xargs shasumはチェックサムファイル自体のチェックサムを(早期に)生成し、チェックに失敗します。

検索| xargs shasumはチェックサムファイル自体のチェックサムを(早期に)生成し、チェックに失敗します。

私の問題(を含むスクリプト#!/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合計を計算することです(最大深度は後で変更される可能性があります)。 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フラグを使用してxargsfindコマンドを実行する前に、出力ファイルを生成して追加のファイルを見つけてチェックサムを見つけました。

回避策として、チェックサムを別の場所(一時ディレクトリを介してmktemp)に保存したり、検索から特に除外したりすることがわかりますが、なぜそれが機能するのかを理解したいと思います。役に立たないようです。たとえば、最初のコマンドが出力ファイルがすでにディスクにあるかどうかを確認した場合、正解は得られません。

答え1

以下を使用してファイルが到着するのを防ぎますxargs

find . -maxdepth 1 -type f ! -name sums.sha1 -printf '%P\n' |
  xargs -r shasum -- > sums.sha1

スペース、改行、引用符、またはバックスラッシュを含むファイル名に関する問題を回避するには、次のようにします。

find . -maxdepth 1 -type f ! -name sums.sha1 -printf '%P\0' |
  xargs -r0 shasum -- > sums.sha1

代わりに。

これはで--始まらないためです-。しかし--print0-printf '%P\0'---

答え2

使用しているので-maxdepth 1再帰したくないとします。その場合は、シェルで実行します。

for f in ~/test/*; do
    shasum -- "$f"
done > sums.sha1

ディレクトリをスキップするには、次のようにします。

for f in ~/test/*; do
    [ ! -d "$f" ] && shasum -- "$f"
done > sums.sha1

再帰が本当に必要であり、それを使用している場合は、bash次のようにします。

shopt -s globstar
for f in ~/test/**; do
    [ ! -d "$f" ] && shasum -- "$f"
done > sums.sha1

これらすべての方法には、スペース、改行、またはその他の項目を含む任意のファイル名で作業できるという利点があります。

答え3

そしてzsh

shasum -- *(D.) > sums.sha1

glob はリダイレクト前に拡張されるため、sums.sha1最初に存在しない限り含まれません。

Dドットファイル(隠しファイル)ですfind.通常のファイル(たとえば、あなたのファイル)のみを選択します-type f

とにかくsums.sha1最初に存在する場合を除外するには、次のようにします。

setopt extendedglob # best in ~/.zshrc
shasum -- ^sums.sha1(D.) > sums.sha1

走っている人は参考にしてください一つshasumコマンドを使用しているため、リストが大きい場合は「Arg list too long」エラーが表示されることがあります。この問題を解決するには:

autoload zargs
zargs -e/ -- *(D.) / shasum > sums.sha1

という名前を避ける./*よりも使用することをお勧めします。*-

答え4

find / xargsなどの代わりにsha1deepをしたいかもしれません。しかし、他のパッケージにあるかもしれません。私のボックスはmd5deepパッケージにあります。

他の人が言ったように、sums.sha1はfindが始まる前にシェルによって生成されます。! -name sums.sha1toを使用するトリックはwillfindのように動作します。

find -maxdepth 1 -type f -printf '%P\n' | xargs shasum | grep -v ' sums\.sha1$' > sums.sha1

関連情報