私の問題(を含むスクリプト#!/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
フラグを使用してxargs
findコマンドを実行する前に、出力ファイルを生成して追加のファイルを見つけてチェックサムを見つけました。
回避策として、チェックサムを別の場所(一時ディレクトリを介して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.sha1
toを使用するトリックはwillfind
のように動作します。
find -maxdepth 1 -type f -printf '%P\n' | xargs shasum | grep -v ' sums\.sha1$' > sums.sha1