bashスクリプトでファイルのサイズを取得するにはどうすればよいですか?


246

bashスクリプトでファイルのサイズを取得するにはどうすればよいですか?

これを後で使用できるようにbash変数に割り当てるにはどうすればよいですか?



1
このペアpvcat進捗状況とETAを:)示しcopyコマンドの
sudoの

stat -c%s file.name
neverMind9

回答:


242

GNUシステム上での最善策:

stat --printf="%s" file.any

man statから:

%s合計サイズ(バイト単位)

bashスクリプトで:

#!/bin/bash
FILENAME=/home/heiko/dummy/packages.txt
FILESIZE=$(stat -c%s "$FILENAME")
echo "Size of $FILENAME = $FILESIZE bytes."

注:Mac OS Xの端末でstatを使用する方法については、@ chbrownの回答を参照してください。


7
@ haunted85 statは、LinuxまたはCygwin(stat標準ではありません)を使用していると仮定すると、最も簡単な方法です。ユージンによって提案ポータブルです。wc -c
ジル

2
stat: illegal option -- c
ユリアンオノフレイ

stat --printf="%s" file.txtDebian Jessieで何も出力しません
...-woohoo

5
MacOSでは、これは機能しますstat -f%z myfile.tar
。– ccpizza

2
@woohooプロンプトは出力を上書きします。man stat--printfは末尾の改行を省略します。--formatまたは-cを使用して出力を表示します。比較することによって、より多くの洞察を得るstat --printf="%s" file.any | xxd -stat -c "%s" file.any | xxd -

92
file_size_kb=`du -k "$filename" | cut -f1`

使用に関する問題statは、それがGNU(Linux)拡張機能であることです。 du -kそしてcut -f1 POSIXによって指定されたため、任意のUnixシステムに移植されています。

たとえば、Solarisにはbashが付属していstatますが、bashは付属していません。したがって、これは完全に仮説ではありません。

ls 出力の正確な形式が指定されていないという点で同様の問題があります。そのため、出力の解析は移植性のある方法で実行できません。 du -hGNU拡張機能でもあります。

可能な場合は携帯用構造物に固執すると、将来誰かの生活が楽になります。たぶんあなた自身。


48
duファイルのサイズを示すのではなく、ファイルが使用するスペースの量を示します。これは微妙に異なります(通常、レポートされるduサイズは、ファイルのサイズを最も近いブロック数に切り上げたものです。通常は512Bまたは1kBまたは4kBです)。
ジル

7
@Gilles、スパースファイル(つまり、穴のあるファイル)は、長さより短いと報告します。
フォンブランド

5
これは、--bytesまたはの-b代わりに-k、受け入れられる回答である必要があります。
Amedee Van Gasse

1
-h(「人間」)オプションはdu、一般的な場合に最も適切な回答を生成しfile_size=`du -h "$filename" | cut -f1ます。K(キロバイト)、M(メガバイト)、またはG(ギガバイト)を適宜表示するためです。
フララウ

1
@fralau:OPは「これをbash変数に割り当てて後で使用できるようにする」ことを望んでいるため、人間が読める近似値ではなく、実際の数値が必要になる可能性が非常に高くなります。また、-hGNU拡張機能です。標準
Nemo

74

「単語数」コマンド(wc)を使用することもできます。

wc -c "$filename" | awk '{print $1}'

問題wcは、ファイル名を追加し、出力をインデントすることです。例えば:

$ wc -c somefile.txt
    1160 somefile.txt

ファイルサイズカウントを取得するためだけに完全なインタプリタ言語またはストリームエディタのチェーンを避けたい場合は、ファイルから入力をリダイレクトしwcて、ファイル名が表示されないようにします。

wc -c < "$filename"

この最後の形式をコマンド置換で使用すると、シェル変数として探していた値を簡単に取得できます(以下のGillesで説明)。

size="$(wc -c <"$filename")"

30
wc -c <"$FILENAME"したがって、他のクラフトのないサイズが得られsize=$(wc -c <"$FILENAME")ます。
ジル

6
もう1つのポイント:wc -c < file少なくともOS Xでテストしたところ、非常に高速であるようです。wcには、-cのみを指定した場合にファイルを統計しようとする頭脳があると推測しています。
エドワードフォーク

4
@EdwardFalk:GNU wc -cはを使用fstatしますが、ファイルの最後から2番目のブロックをシークし、最後の最大st_blksizeバイトを読み取ります。どうやらこれは、Linuxのファイルであるためである/proc/sys例えばだけ近似しているのstatサイズを有し、かつwc実際のサイズではなく、STAT-報告されたサイズを報告することを望んでいます。wc -c以外のサイズを報告するのは奇妙だと思いwcますが、通常のディスクファイルであり、メモリにない場合は、ファイルからデータを読み取ることは考えられません。それとも悪いことに、ニアラインテープストレージ...
ピーターコルド

1
printfインデントがまだ残っているようです(例:printf "Size: $size"->)size: <4 spaces> 54339。一方echo、空白は無視されます。一貫性を保つ方法はありますか?
ユージンクラブホフ

2
@keithpjolley:を呼び出すことによりfstat。実行strace wc -c </etc/passwdしてみて、それが何をしているかを見ることができます。
ニモ

48

BSD(Mac OS X)にstatは、異なる形式引数フラグと異なるフィールド指定子があります。からman stat(1)

  • -f format:指定された形式を使用して情報を表示します。有効な形式の説明については、「形式」セクションを参照してください。
  • ... FORMATSセクション...
  • z:ファイルのサイズ(バイト単位)。

だから今すべて一緒に:

stat -f%z myfile1.txt

28

サイズの意味に依存します。

size=$(wc -c < "$file")

ファイルから読み取ることができるバイト数を提供します。IOW、それはファイルのコンテンツのサイズです。ただし、ファイルの内容を読み取ります(ほとんどのwc実装では、ファイルが最適化として通常ファイルまたは通常ファイルへのシンボリックリンクである場合を除きます)。それには副作用があるかもしれません。たとえば、名前付きパイプのために、何を読んでてきたことは、もはや再び読み込むことができず、のようなもののため/dev/zeroか、/dev/random無限の大きさであり、しばらく時間がかかるだろう。またread、ファイルへのアクセス許可と最後のアクセスタイムスタンプが必要であることも意味しますが更新される可能性があります。

これは標準で移植可能ですが、一部のwc実装ではその出力に先頭の空白が含まれることがあることに注意してください。それらを取り除く1つの方法は以下を使用することです:

size=$(($(wc -c < "$file")))

または内空の算術式に関するエラーを回避するdashか、yashときwc(ファイルを開くことができないときのように)出力を生成しません。

size=$(($(wc -c < "$file") +0))

ksh93wc組み込まれているので(有効にする場合はとして呼び出すこともできcommand /opt/ast/bin/wcます)、そのシェル内の通常のファイルに対して最も効率的になります。

さまざまなシステムにはstatstat()またはlstat()システムコールへのインターフェイスと呼ばれるコマンドがあります。

iノードで見つかったこれらのレポート情報。その情報の1つがst_size属性です。通常のファイルの場合、それはコンテンツのサイズです(エラーがない場合にそこから読み取ることができるデータの量(ほとんどのwc -c実装が最適化で使用するものです))。シンボリックリンクの場合、それはターゲットパスのバイト単位のサイズです。名前付きパイプの場合、システムに応じて、0またはパイプバッファーに現在あるバイト数のいずれかです。システムに応じて、0または基礎となるストレージのバイト単位のサイズを取得するブロックデバイスについても同じです。

その情報を取得するためにファイルの読み取り権限は必要ありません。リンク先のディレクトリに対する検索権限のみが必要です。

時系列順に、以下があります。

  • IRIXstat(90年代):

    stat -qLs -- "$file"

    ()または次のst_size属性を返します:$filelstat()

    stat -s -- "$file"

    $fileシンボリックリンクの場合を除き、シンボリックst_sizeリンク解決後のファイルの場合と同じです。

  • zsh statモジュールに組み込まれた(現在はとしても知られzstatていzsh/statます)(ロード済みzmodload zsh/stat)(1997):

    stat -L +size -- $file # st_size of file
    stat +size -- $file    # after symlink resolution

    または変数に保存するには:

    stat -L -A size +size -- $file

    明らかに、それはそのシェルで最も効率的です。

  • GNUstat(2001); stat2005年からBusyBoxでも(GNUからコピーstat):

    stat -c %s -- "$file"  # st_size of file
    stat -Lc %s -- "$file" # after symlink resolution

    -LIRIXまたはに比べての意味が逆になっていることに注意してくださいzsh stat

  • BSDstat(2002):

    stat -f %z -- "$file"  # st_size of file
    stat -Lf %z -- "$file" # after symlink resolution

または、次のようなスクリプト言語のstat()/ lstat()関数を使用できますperl

perl -le 'print((lstat shift)[7])' -- "$file"

AIXには、すべての(シンボリックリンクでは機能しないため)情報をすべてダンプするistatコマンドがあり、次のように後処理できます。stat()lstat()

LC_ALL=C istat "$file" | awk 'NR == 4 {print $5}'

詳細を理解するのに役立つ @JeffSchallerに感謝します)。

tcsh

@ size = -Z $file:q

(シンボリックリンク解決後のサイズ)

GNUがそのstatコマンドを導入するずっと前にfind、その-printf述語(すでに1991年)を使用してGNU コマンドで同じことが達成できました。

find -- "$file" -prune -printf '%s\n'    # st_size of file
find -L -- "$file" -prune -printf '%s\n' # after symlink resolution

一つの問題はしかし場合には動作しないです$fileから始まる-かであるfind述語を(のような!(...)。

stat()/ lstat()情報を取得する標準コマンドはlsです。

POSIXly、次のことができます:

LC_ALL=C ls -dn -- "$file" | awk '{print $5; exit}'

-Lシンボリックリンクの解決後に同じものを追加します。5 番目のフィールドはサイズではなくデバイスのメジャー番号ですが、デバイスファイルでは機能しません。

ブロックデバイスの場合、stat()に0を返すシステムにはst_size通常、ブロックデバイスのサイズを報告する他のAPIがあります。たとえば、LinuxにはがありBLKGETSIZE64 ioctl()、ほとんどのLinuxディストリビューションにはblockdev、それを利用できるコマンドが付属しています。

blockdev --getsize64 -- "$device_file"

ただし、そのためにはデバイスファイルの読み取り権限が必要です。通常、他の方法でサイズを導出することが可能です。たとえば(Linuxでも):

lsblk -bdno size -- "$device_file"

空のデバイスを除いて動作するはずです。

すべてのシーク可能なファイル(通常のファイル、ほとんどのブロックデバイス、一部のキャラクターデバイスを含む)で機能するアプローチは、ファイルを開いて最後までシークすることです。

  • ありzshzsh/systemモジュールのロード後):

    {sysseek -w end 0 && size=$((systell(0)))} < $file
  • ksh93

    < "$file" <#((size=EOF))

    または

    { size=$(<#((EOF))); } < "$file"
  • perl

    perl -le 'seek STDIN, 0, 2 or die "seek: $!"; print tell STDIN' < "$file"

名前付きパイプのために、我々はいくつかのシステム(少なくともAIX、Solaris版、HP / UX)はパイプバッファ内のデータ量を利用可能にすることを見てきましたstat()s「をst_size。一部の(LinuxやFreeBSDなど)しません。

少なくともLinuxではFIONREAD ioctl()、パイプを開いた後に使用できます(ハングしないように、読み取り+書き込みモードで)。

fuser -s -- "$fifo_file" && 
  perl -le 'require "sys/ioctl.ph";
            ioctl(STDIN, &FIONREAD, $n) or die$!;
            print unpack "L", $n' <> "$fifo_file"

ただし、パイプの内容は読み取れません、ここで名前付きパイプを開くだけでは副作用が発生する可能性があることに注意してください。私たちは、使用しているfuser最初のいくつかのプロセスがすでにそれを軽減するためのオープンパイプを持っていることを確認することではなくて、それは誰にでもありませんfuserすべてのプロセスをチェックすることができないかもしれません。

さて、これまでのところ、ファイルに関連付けられているプライマリデータのサイズのみを考慮してきました。メタデータのサイズと、そのファイルを保存するために必要なすべてのサポートインフラストラクチャは考慮されません。

によって返される別のiノード属性はstat()ですst_blocks。これは、ファイルのデータ(および場合によってはLinuxのext4ファイルシステムの拡張属性などの一部のメタデータ)を格納するために使用される512バイトブロックの数です。iノード自体や、ファイルがリンクされているディレクトリのエントリは含まれません。

サイズとディスク使用量は、圧縮、スパース性(一部のメタデータ)、一部のファイルシステムの間接ブロックなどの余分なインフラストラクチャが後者に影響を与えるため、必ずしも密接に関連しているわけではありません。

これは通常、duディスク使用量のレポートに使用されます。上記のコマンドのほとんどは、その情報を取得できます。

  • POSIXLY_CORRECT=1 ls -sd -- "$file" | awk '{print $1; exit}'
  • POSIXLY_CORRECT=1 du -s -- "$file" (ファイル内のファイルのディスク使用量を含むディレクトリ用ではありません)。
  • GNU find -- "$file" -printf '%b\n'
  • zstat -L +block -- $file
  • GNU stat -c %b -- "$file"
  • BSD stat -f %b -- "$file"
  • perl -le 'print((lstat shift)[12])' -- "$file"

明らかに最も包括的かつ情報的な答え。ありがとうございました。私はBSDを使用して、クロスプラットフォームのbashスクリプトを作成するためにこれを使用することができますし、GNUは、情報統計
oligofren

1
楽しい事実:GNU coreutils wc -cはを使用しfstatますが、最後の最新st_blksizeバイトを読み取ります。どうやら、Linuxのファイルであるため、これはある/proc/sys例えばのみ概算でありSTATサイズを有します。これは正確さには適していますが、ファイルの終わりがメモリ上ではなくディスク上にある場合(特に、ループ内の多くのファイルで使用される場合)には不適切です。また、ファイルをニアラインテープストレージに移行した場合、またはFUSEの透過的解凍ファイルシステムなどに移行した場合は非常に悪いです。
ピーターコーデス

この作業もしませんls -go file | awk '{print $3}'
スティーブンペニー

@StevenPenny -goはSysVのものであり、BSDでは動作しません(POSIXのオプション(XSI))。また、必要になりますls -god file | awk '{print $3; exit}'-dディレクトリで動作するexitため、ターゲットに改行があるシンボリックリンクのため)。デバイスファイルの問題も残ります。
ステファンシャゼラス

1
@αғsнιηUnix APIは、テキストファイルとバイナリファイルを区別しません。それはすべてバイトのシーケンスです。一部のアプリケーションは、これらのバイトをテキストとして解釈したい場合がありますがwc -c、バイト数を報告するものではないことは明らかです。
ステファンシャゼラス

22

このスクリプトは、ファイルサイズを計算する多くの方法を組み合わせています。

(
  du --apparent-size --block-size=1 "$file" 2>/dev/null ||
  gdu --apparent-size --block-size=1 "$file" 2>/dev/null ||
  find "$file" -printf "%s" 2>/dev/null ||
  gfind "$file" -printf "%s" 2>/dev/null ||
  stat --printf="%s" "$file" 2>/dev/null ||
  stat -f%z "$file" 2>/dev/null ||
  wc -c <"$file" 2>/dev/null
) | awk '{print $1}'

このスクリプトは、Linux、BSD、OSX、Solaris、SunOSなどを含む多くのUnixシステムで動作します。

ファイルサイズはバイト数を示します。これは見かけのサイズです。これは、ファイルが通常のディスクで使用するバイト数で、特別な圧縮、特別なスパース領域、未割り当てブロックなどはありません。

このスクリプトには、より多くのヘルプとオプションが含まれる製品版があります:https : //github.com/SixArm/file-size


9

statは、最も少ないシステムコールでこれを行うようです。

$ set debian-live-8.2.0-amd64-xfce-desktop.iso

$ strace stat --format %s $1 | wc
    282    2795   27364

$ strace wc --bytes $1 | wc
    307    3063   29091

$ strace du --bytes $1 | wc
    437    4376   41955

$ strace find $1 -printf %s | wc
    604    6061   64793

8

ls -l filename ファイルサイズ、アクセス許可、所有者など、ファイルに関する多くの情報を提供します。

5列目のファイルサイズ。バイト単位で表示されます。以下の例では、ファイルサイズは2 KB未満です。

-rw-r--r-- 1 user owner 1985 2011-07-12 16:48 index.php

編集:これは明らかにstatコマンドほど信頼性が高くありません。


両方ls -lstatコマンドが信頼できるサイズ情報を提供すると思います。私はそれとは逆の言及を見つけませんでした。ls -sブロック数でサイズを指定します。
dabest1

2
@ dabest1は、別のUNIXでは出力が異なる可能性があるという意味で信頼できません(一部のUNIXではそうです)。
ユージンブジャク

はい、IIRC、Solarisはデフォルトでグループ名を表示しなかったため、出力の列が少なくなりました。
エドワードフォーク

定義された形式では、サイズは空白で囲まれた純粋な数値であり、日付年は純粋な数値であるため、グループが存在するかどうかにかかわらず、正規表現を使用してuser + ownerを1つのフィールドとして扱うことができます。(読者のための演習!)
MikeW

5

du filename ディスク使用量をバイト単位で通知します。

du -h filenameは、人間が読める形式でサイズを提供することを好みます。


2
それまたはstat -c "%s";)

1
このフレーバーはdu、単純なバイト数ではなく、1024バイトのブロック単位でサイズを出力します。
ピーターライオンズ

標準でduは、512バイト単位の数で出力されることに注意してください。GNU duPOSIXLY_CORRECT、その環境で呼び出されない限り、代わりにkibibytesを使用します。
ステファンシャゼル16年

1
タイプがdirectoryのファイルの場合、ディレクトリのディスク使用量だけでなく、(再帰的に)内の他のすべてのファイルの使用量も提供します。
ステファンシャゼル16年

3

シェルスクリプトに委任できる小さなユーティリティ関数を作成します。

#! /bin/sh -
# vim: set ft=sh

# size utility that works on GNU and BSD systems
size(){
    case $(uname) in
        (Darwin | *BSD*)
            stat -Lf %z -- "$1";;
        (*) stat -c %s -- "$1"
    esac
}

for f do
    printf '%s\n' "$f : $(gzip < "$f" | wc -c) bytes (versus $(size "$f") bytes)"
done

@StéphaneChazelasの回答からの情報に基づいています。


gzip -v < file > /dev/nullファイルの圧縮率の確認も参照してください。
ステファンシャゼル

@StéphaneChazelasは改善したと思うかどうかわかりません。これらのcaseステートメントは、初心者を簡単に先送りできます。私は確かにそれらを正しくする方法を決して覚えていません:-)あなたがそれをしたので、本質的にcase文はよりポータブルです?私は2つ以上のケースがあるときにポイントを見ますが、そうでない場合は... +
オリゴフレン

1
好みの問題でもあると思いますが、ここではcaseステートメントを使用したい典型的なケースです。caseパターンマッチングを行うBourne / POSIXコンストラクトです。[[...]]ksh / bash / zshのみです(バリエーションあり)。
ステファンシャゼル

2

AWK 1ライナーを見つけ、バグがありましたが、修正しました。また、TeraBytesの後にPetaBytesを追加しました。

FILE_SIZE=234234 # FILESIZE IN BYTES
FILE_SIZE=$(echo "${FILE_SIZE}" | awk '{ split( "B KB MB GB TB PB" , v ); s=1; while( $1>1024 ){ $1/=1024; s++ } printf "%.2f %s", $1, v[s] }')

statがすべての単一のシステムにあるとは限らないことを考慮すると、ほとんど常にAWKソリューションを使用できます。例; Raspberry Piにはstatはありませんが、awkがあります。


1
OPが求めたものではなく、すてきな小さな作品。
ジプシースペルウィーバー

0

もう一つのPOSIX準拠した方法は、使用することですawkそのにlength()改行文字を除いて、入力ファイルの各行に文字で、長さを返す関数。そうすることで

awk '{ sum+=length } END { print sum+NR }' file

にがNR追加されていることを確認sumします。これにより、ファイルで遭遇する文字の総数と改行の総数が得られます。length()関数はawk、デフォルトの手段によって引きとりlength($0)、現在の行全体のためです。


最後の行は改行で終わっていないではない場合:printf 'a\nb' | awk '{ sum+=length } END { print sum+NR }'3が、印刷物4を印刷する必要があります
アイザック・

-1

私は自分でwcオプションが好きです。「bc」と組み合わせると、必要な数だけ小数を取得できます。

「ls -alh」コマンドの「ファイルサイズ」列をわかりやすくするスクリプトを改善しようとしていました。整数のファイルサイズだけが欲しくなく、小数点以下2桁が適しているように思えたので、この説明を読んだ後、以下のコードを思い付きました。

スクリプトにこれを含める場合は、セミコロンで改行することをお勧めします。

file=$1; string=$(wc -c $file); bite=${string% *}; okay=$(echo "scale=2; $bite/1024" | bc);friend=$(echo -e "$file $okay" "kb"); echo -e "$friend"

私のスクリプトは、「画像ファイルの長さを取得する」ためのgpflと呼ばれます。imagemagickでファイルをmogrifyした後、GUI jpegビューアーで画像を開いたり再読み込みする前に使用します。

既に提供され、議論されているものから多くを借りているため、これが「答え」としてどのように評価されるのかわかりません。それで私はそこに置いておきます。

BZT


1
「stat」または「ls」の使用を希望します。通常、ファイル全体を物理的に読み取るため、「wc」を使用してファイルサイズを取得するのは好ましくありません。多くのファイル、または特に大きなファイルがある場合、これには多くの時間がかかります。しかし、あなたのソリューションは創造的です... + 1。
ケビンフェガン

2
ファイルサイズに「wc」よりも「stat」を使用するという考え方に同意しますが、「wc -c」を使用すると、データは読み込まれません。代わりに、lseekを使用してファイルのバイト数を計算します。lingrok.org/xref/coreutils/src/wc.c#228
bbaja42

1
@ bbaja42:GNU Coreutils wcはファイルの最後のブロックを読み取ることに注意してくださいstat.st_size(Linux /proc/sysファイルの場合など)。私は、彼らが数行をそのロジックを下に追加したときに、メインのコメントはより複雑にしないことを決定した推測:lingrok.org/xref/coreutils/src/wc.c#246
ピーター・コルド

-1

最も速くて簡単な(IMO)方法は次のとおりです。

bash_var=$(stat -c %s /path/to/filename)

2
次に、statに言及している既存の回答の1つ以上に投票します。もう一度繰り返す必要はありません...
ジェフシャラー

1
@JeffSchaller私はあなたの指示についてステファンの答えを支持しました。私の目的には複雑すぎると思います。だからこそ、私はこの単純な答えを同じような心の魂のために投稿しました。
WinEunuuchs2Unix

1
ありがとうございました; それだけということだ第六「STAT」の答えのインスタンスは、このQ&Aを単純化せず、むしろ新しい読者が自分自身を尋ねるになるだろう「他のものとは異なり、この答えはどのように?」少ないのではなく、より多くの混乱につながります。
ジェフシャラー

@JeffSchallerだと思う。しかし、私は多くの文句を言うことができdu及びwc免責条項が持つべき答えTHISを決してしない実際の生活の中で。今夜、実生活のアプリケーションで自分の答えを使ってみたところ、共有する価値があると思いました。私たちは皆意見が肩をすくめていると思います。
WinEunuuchs2Unix
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.