web-dev-qa-db-ja.com

lsとawkを組み合わせても正確なサイズが表示されないのはなぜですか?

私はハードドライブ上のファイルのサイズを正確なバイト単位で見つけようとしていますが、サイズが大きくなりすぎると数値がすべて変わってしまいます(1.998329e + 12など)。これをやめたり、これを正確なバイトに変換したりできますか?

コマンドは次のとおりです。

ls -lR | grep -v '^d' | awk '{total += $5} END {print "Total:", total}'

正確なバイトの画像:

img

奇妙な数字の画像:

img

  • 正確なバイトが表示されるのを停止する前のカットオフポイントは、約500 GBのようです
  • コマンドdu -sbは、ディレクトリの大きさに関係なく正確なバイト数を正しく表示します。
  • Ubuntu Gnome 15.10 64ビット(日本語と英語)とLinux Mint 17.3 Cinnamon 64ビット(日本語)を試しました
  • 私のドライブはntfsなので、ext4としてフォーマットし、ファイルをコピーしてみました。結果はntfsと同じです。
4
パンツ

問題は、MAWK(UbuntuにインストールされたAWKバリアント)がデフォルトで2147483647(231-1)科学表記法:

% awk -W version
mawk 1.3.3 Nov 1996, Copyright (C) Michael D. Brennan

compiled limits:
max NF             32767
sprintf buffer      2040
% printf '2147483647\n' | awk '{x += $1; print x}'
2147483647
% printf '2147483648\n' | awk '{x += $1; print x}'
2.14748e+09

printf *の代わりに、フォーマット指定子でprintを使用できます。

printf '2147483648\n' | awk '{x += $1; printf "%.0f\n", x}'
% printf '2147483648\n' | awk '{x += $1; printf "%.0f\n", x}'
2147483648

あなたの場合:

ls -lR | grep -v '^d' | awk '{total += $5} END {printf "Total:%.0f\n", total}'
ls -lR |
    grep -v '^d' |
    awk '
        {
            total += $5
        }
        END {
            printf "Total:%.0f\n", total
        }
    '

これにより、AWKはtotalを科学表記ではなく10進表記で印刷するように強制されます。

ただし、別の注意事項では、 ls を解析しないでください。

より繊細な方法は、find + statを使用することです。

find . -type f -exec stat -c '%s' {} + | awk '{total += $1} END {printf "Total:%.0f\n", total}'
find . -type f -exec stat -c '%s' {} + |
    awk '
        {
            total += $1
        }
        END {
            printf "Total:%.0f\n", total
        }
    '

* %.0fは、printf2147483647(231-1)、%dを書式指定子として使用すると、常に2147483647として出力されます。 %.0fの制限は、9007199254740992(253)、これが懸念事項である場合(有益な情報をRotsorに感謝します)。

5
kos

TL; DRlsおよびawkは、目的には不要です。分析するディレクトリでdu -cbまたはdu -bsを使用します。

あなたの目的は

  1. すべてのファイルを検索
  2. サイズ(バイト単位)を見つける
  3. それらすべての総計を生成する

これらのすべてのアクションは、duによって実行できます。

$ du -bs $HOME 2>/dev/null                                                                 
76709521942 /home/xieerqi

duには2つの「モード」があることに注意してください-サイズがどのくらいのファイルであるかを示すことができますORどれだけの実際のディスク容量(実際の、物理的な不動産)。すべてのファイルの合計サイズに関心があるため、見かけのファイルサイズが必要です。 -bフラグはそれを正確に示します(-b--apparent-size --block-size=1のエイリアスです)。

おそらく、より簡潔で適切な解決策は、du -bcを目的のディレクトリで直接使用することです。たとえば、ホームディレクトリのサイズは約76 GBです

$ du -bc $HOME 2> /dev/null  | tail -1                    
76694582570 total

何らかの理由で、フォルダーサイズとファイルサイズの違いを心配しています。コメントで次のように述べています。

ファイルサイズは一定であるのにディレクトリサイズが異なるため、私はlsを好むでしょう。

duは再帰的で、ファイルサイズを合計します。また、ディレクトリの静的サイズは4096バイト(4k)ですが、duを使用すると、du -bs directory_nameの結果に含まれます。このことを考慮:

$ du -b suse/openSUSE-Leap-42.1-DVD-x86_64.iso                                             
4648337408  suse/openSUSE-Leap-42.1-DVD-x86_64.iso

$ du -b suse/                                                                              
4648341504  suse/

$ bc <<< "4648337408+4096" 
4648341504

$ mkdir suse/another_dir  

$ du -b suse/another_dir                                                                   
4096    suse/another_dir

$ du -bs suse/                                                                             
4648345600  suse/
5

内部では、awkはすべての計算を倍精度浮動小数点数を使用して実行します。デフォルトでは printf(3) 書式指定子%.6gを使用して出力します。つまり、数値が6桁を超える場合は E-notation に切り替わります。見ました。これを回避するには、変数OFMTを設定します。

ls -lR |
    awk 'BEGIN { OFMT = "%d" }  
         /^-/  { total += $5 } 
         END   { print "Total:", total }'

ただし、上限があり、それを超えるとできない正確なバイト数が得られません。合計の下位ビットの四捨五入を開始します。 500ギガバイト= 500 * 1024 * 1024 * 1024 = 536870912000≈239。通常のIEEE浮動小数点では、これはその制限を安全に下回ります(roughly252)。ただし、十分に大きいため、適切な「bignums」(サイズ無制限の整数)を備えたプログラミング言語を使用すると、個人的には気分が良くなります。たとえば、Python:

#! /usr/bin/python
import os
import sys

space = 0L  # L means "long" - not necessary in Python 3
for subdir, dirs, files in os.walk(sys.argv[1]):
    for f in files:
        space += os.lstat(os.path.join(subdir, f)).st_size

sys.stdout.write("Total: {:d}\n".format(space))

これは、名前に異常な文字が含まれるファイルの問題の影響もまったく受けません。また、隠しファイルによって消費されるスペースをカウントします。

これにより、各ファイルで見えるバイト数が計算されます。これは、ls -lが出力するものと同じです。代わりに実際にディスクで占有されているバイト数duが出力するもの)が必要な場合は、.st_size.st_blocks * 512に置き換えます。 (はい、st_blksizeが異なる数値であっても、乗数は常に512です。)

4
zwol

ここに表示されるのは、大きな数字を表示する方法です。例えば:

1.23e+3 = 1.23*10^3 = 1230

私の知る限り、これをオフにすることはできませんが、質問で書いたように、duの動作は異なるため、これを使用することをお勧めします。それ以外の場合は、数値を変換する必要があります。

3
Wayne_Yux