ディレクトリブランチ内の特定のファイルの合計サイズを見つける


140

たとえば、イメージストレージディレクトリがあり、./photos/john_doeその中に複数のサブディレクトリがあり、そこに多くの特定のファイルが存在すると仮定します(たとえば、*.jpg)。john_doeブランチの下にあるこれらのファイルの要約サイズを計算するにはどうすればよいですか?

試しましたdu -hs ./photos/john_doe/*/*.jpgが、これは個々のファイルのみを表示します。また、これjohn_doeはのようjohn_doe/june/にディレクトリの最初のネストレベルのみを追跡しますが、スキップしますjohn_doe/june/outrageous/

それでは、特定のファイルのサイズを合計して、ブランチ全体をどのように走査できますか?

回答:


183
find ./photos/john_doe -type f -name '*.jpg' -exec du -ch {} + | grep total$

duファイルリストが非常に長いために複数の呼び出しが必要な場合、複数の合計が報告され、合計する必要があります。


7
find -iname 'file *' -exec du -cb {} + | grep total $ | カット-f1 | 貼り付け-sd +-| bc#合計バイトサイズ
MichalČizmazia15年

3
システムが他の言語で動作する場合、total $をポーランド語のrazem $などの他の単語に変更する必要があります。
ズビスク

1
あなたは追加することができますLC_ALL=POSIX:常にこのような合計をgrepする接頭辞としてLC_ALL=POSIX find ./photos/john_doe -type f -name '*.jpg' -exec du -ch {} + | grep total$
スヴェン

2
を使用していない場合は-name、grepをに変更するgrep -P "\ttotal$"か、「total」で終わるすべてのファイルをキャプチャします。
-thdoan

3
@MichalČizmaziaいくつかのシェル(たとえば、Git Bash for Windows)は付属していませんbc。そのため、よりポータブルなソリューションをfind -name '*.jpg' -type f -exec du -bc {} + | grep total$ | cut -f1 | awk '{ total += $1 }; END { print total }'
次に示します。– thdoan

50
du -ch public_html/images/*.jpg | grep total
20M total

.jpgこのディレクトリ内のファイルの合計使用量を教えてくれます。

複数のディレクトリを処理するには、おそらくこれをfind何らかの形で組み合わせる必要があります。

あなたは見つけるかもしれないデュコマンドの例を便利(それも含みfind


2
これは、基礎となるディレクトリを横断しませんか?
mbaitoff

これは受け入れられているソリューションよりも入力が簡単ですが、半分しか正しくありません。サブディレクトリに画像は含まれません。すべてのファイルが1つのディレクトリにあるかどうかを知っておくと便利です。
gbmhunter

@gbmhunter -Rパラメータを-chに追加すると、ディレクトリツリーを再帰的に走査するときにサブディレクトリも取得されると思います。私は現在、確認のために試してみるためにコンピューターを使用していません。
レボン

1
man7.org/linux/man-pages/man1/du.1.htmlに-Rオプションが表示されません。そして、この場合、再帰的なオプションが役立つとは思わない。なぜなら、シェルは引数をに渡す前にグロブ展開を行っているからだ。du
gbmhunter

22

主に、次の2つが必要です。

  • 総計を生成するように指示するための-cオプションdu
  • いずれか**起動指示)またはfind例えば)またはサブディレクトリを横断します。
du -ch -- **/*.jpg | tail -n 1

非常に良い返信。findを使用するよりも簡単です(*または**がディレクトリ構造に一致する限り)
アンドレデミランダ

また、非常に長いファイルのリストを処理できますが、使用findすると誤った結果が返される可能性があります。
エリックフォーニー

bash brace拡張では、ワイルドカードの複数のセットも測定できます。du -ch -- ./{dir1,dir2}/*.jpgまたはdu -ch -- ./{prefix1*,prefix2*}.jpg
J.Money

@EricFournieただしArgument list too long、約30万のテキストファイルを処理するとエラーが発生しました。
xtluo

コマンドの引数の最大数(この場合、ワイルドカード拡張によって返されるファイル名)は、で確認できますgetconf ARG_MAX。さらにファイルがある場合は、ファイルを1つずつ処理するか、forループでバッチ処理する必要があります。
エリックフォーニー

17

最終的な答えは:

{ find <DIR> -type f -name "*.<EXT>" -printf "%s+"; echo 0; } | bc

RAMによる制限はありませんが、さらに高速なバージョンですが、これにはbignumサポート付きのGNU AWKが必要です。

find <DIR> -type f -name "*.<EXT>" -printf "%s\n" | gawk -M '{t+=$1}END{print t}'

このバージョンには次の機能があります。

  • find探しているファイルを指定するすべての機能
  • 数百万のファイルをサポート
    • ここの他の答えは、引数リストの最大長によって制限されます
  • 最小限のパイプスループットで3つの単純なプロセスのみを生成します
    • ここでの多くの答えはC + Nプロセスを生み出します。Cは一定の定数で、Nはファイルの数です
  • 文字列操作を気にしません
    • このバージョンでは、grepの実行や正規表現は行われません。
    • まあ、findファイル名の単純なワイルドカードマッチングを行います
  • 必要に応じて人間が読める形式に合計をフォーマット(例えば5.5K176.7M、...)
    • そのために追加 | numfmt --to=si

この回答のシンプルさが気に入っていますが、開き中かっこの後と閉じ中かっこの前にスペースを導入したときにのみ機能しました。私はそれが本当に「無限」の数のファイルをサポートするのだろうかと思う:)
andyb

1
@andybはフィードバックに感謝します。BASHには中括弧の周りのスペースが実際に必要です。私はZSHを使用しているので、気づきませんでした。そして、ファイルの数が、BCのメモリ使用量などのシステムで使用可能なRAMによって制限されては中の数字の流れとして、ゆっくりと成長する。
月Chren - rindeal

8

これまでに与えられた答えは、findからduに渡されるファイルリストが非常に長く、findがリストを自動的にチャンクに分割することを考慮していないため、複数回出現しtotalます。

あなたのいずれかを行うことができgrep total(ロケール!)、手動でまとめるか、別のコマンドを使用します。私の知る限り、findで見つかったすべてのファイルの総計(キロバイト)を取得する方法は2つしかありません。
find . -type f -iname '*.jpg' -print0 | xargs -r0 du -a| awk '{sum+=$1} END {print sum}'

説明
find . -type f -iname '*.jpg' -print0:大文字小文字に関係なく拡張子がjpgのすべてのファイル(つまり、*。jpg、*。JPG、*。Jpg ...)を検索し、それらを出力します(ヌル終了)。
xargs -r0 du -a:-r:Xargsは、引数が渡されていない場合でもコマンドを呼び出しますが、これは-rによって防止されます。-0は、ヌルで終了する文字列(改行で終了しない)を意味します。
awk '{sum+=$1} END {print sum}':前のコマンドで出力されたファイルサイズを合計する

また、参考のために、他の方法は
find . -type f -iname '*.jpg' -print0 | du -c --files0-from=-


追加のヒント:23428ファイル(22323はイメージ)を使用するHDDでは、最初のメソッドは1秒実行され、2番目のメソッドは3.8秒実行されます。
1

両方ともGNUシステムを想定していることに注意してください。最初のものは、ファイル名に改行文字が含まれていないことを前提としています。
ステファンシャゼル14

du --file0-from最初に実行したので(キャッシュ効果)より時間がかかったに違いありません。
ステファンシャゼル14

ではxargs、いくつかdu -aが実行される可能性があるため、ハードリンクがある場合は不一致が生じる可能性があります。
ステファンシャゼル14

3

ファイルのリストが大きすぎdu -cて、GNUシステムでの単一の呼び出しに渡すことができない場合は、次のことができます。

find . -iname '*.jpg' -type f -printf '%b\t%D:%i\n' |
  sort -u | cut -f1 | paste -sd+ - | bc

(512バイトブロックの数で表されるサイズ)。duハードリンクを一度だけカウントしようとするように。ハードリンクを気にしない場合は、次のように単純化できます。

(printf 0; find . -iname '*.jpg' -type f -printf +%b) | bc

あなたが代わりにディスク使用量の大きさが必要な場合は、交換してください%b%s。サイズはバイト単位で表されます。


-bash: bc: command not foundCentos-Linux 2.6.32-431.el6.x86_64
yeya

@ yeya、CentOSの展開が壊れているようですね。bcオプションではないPOSIXコマンドです。
ステファンシャゼラス

1

これまでに説明したソリューションは非効率的で(execは高価です)、ファイルリストが長い場合やMac OS Xで機能しない場合は追加の手作業が必要です。次のソリューションは非常に高速で、どのシステムでも機能します。合計回答をGB単位で返します(合計をMB単位で表示する場合は/ 1024を削除します): find . -iname "*.jpg" -ls |perl -lane '$t += $F[6]; print $t/1024/1024/1024 . " GB"'


どちら-iname-ls標準/ポータブルではないため、どのシステムで動作しません。また、改行文字を含むファイル名またはシンボリックリンクターゲットがある場合は、適切に機能しません。
ステファンシャゼラス

また、ディスク使用量ではなく、ファイルサイズの合計が表示されることに注意してください。シンボリックリンクの場合、それが指すファイルではなく、シンボリックリンクのサイズを示します。
ステファンシャゼル

1

Zbyszekが既にコメントで指摘しているように、SHWがあらゆるロケールで動作するようにすごい答えを改善します。

LC_ALL=C find ./photos/john_doe -type f -name '*.jpg' -exec du -ch {} + | grep total$

1

duはディレクトリ階層を自然に横断し、awkはフィルタリングを実行できるため、次のようなもので十分です。

du -ak | awk 'BEGIN {sum=0} /\.jpg$/ {sum+=$1} END {print sum}'

これはGNUなしで機能します。


1
これはstat、検索対象のパターンに対応しないファイルの呼び出しを必要とするため、より高価です。
法律

このソリューションのみが私のMacで動作します。
マティアスM
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.