Bashスクリプトからファイルサイズを取得するには?

Bashスクリプトからファイルサイズを取得するには?

Bashスクリプトからファイルサイズを取得するには?

後で使用するためにbash変数にどのように割り当てますか?

答え1

GNUシステムの場合、最良のオプションは次のとおりです。

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

~から人の統計:

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

Bashスクリプトでは:

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

注:参照@chbrownの返信statBSDまたはmacOSシステムで使用する方法を学びます。

答え2

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

これを使用する際の問題statは、GNU(Linux)拡張であることです。 du -kそしてcut -f1POSIXで指定されているため、すべてのUnixシステムに移植可能です。

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

ls出力の正確な形式が指定されていないため、出力を移植可能に解析できない同様の問題があります。 du -hまた、GNU拡張です。

可能な限り、リムーバブル構造に固執することで、将来的に人々の生活をより簡単にすることができます。たぶんあなた自身のものかもしれません。

答え3

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

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

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

$ wc -c somefile.txt
    1160 somefile.txt

ファイルサイズを計算するために完全な解釈言語またはストリームエディタをリンクしたくない場合は、ファイル名が表示されないようにwcファイルから入力をリダイレクトするだけです。

wc -c < "$filename"

前述のように、最後の形式をコマンド置換と組み合わせて使用​​して、探しているシェル変数の値を簡単に取得できます。ザイルズ次のような。

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

答え4

何を意味するかによって異なりますサイズ

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

ファイルから読み取ることができるバイト数を示します。 IOW、ファイルの内容のサイズ。ただし、ファイルの内容を読みます(ファイルが通常のファイルである場合、またはほとんどの実装wcで最適化として一般ファイルを指すシンボリックリンクではない場合)。副作用がある可能性があります。たとえば、名前付きパイプの場合、読み取った内容は読み取れなくなり、サイズが無限の場合/dev/zeroは時間がかかります。これはまた、ファイルに対する権限が/dev/random必要であることを意味します。read最後のアクセスタイムスタンプファイルの内容が更新されることがあります。

これは標準的で移植可能ですが、一部のwc実装ではこの出力に先行スペースを含めることができます。これを削除する1つの方法は、次のものを使用することです。

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

または、出力が生成されない場合dash(たとえば、ファイルを開くことができない場合)、空の算術式のエラーを避けてください。yashwc

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

ksh93組み込みのwc機能(アクティブなように呼び出すこともできますcommand /opt/ast/bin/wc)があり、このシェルの一般ファイルに最も効果的です。

statさまざまなシステムには、システムコールへのインターフェースであるというコマンドがあります。stat()lstat()

これはインデックスノードで見つかった情報を報告します。情報の1つがst_size属性です。一般ファイルの場合、これはコンテンツのサイズ(エラーなしで読み取ることができるデータ量(wc -cほとんどの実装で最適化に使用するもの))です。シンボリックリンクの場合、宛先パスのサイズ(バイト単位)です。名前付きパイプの場合、システムによっては、この値はゼロまたはパイプバッファ内の現在のバイト数になります。ブロックデバイスの場合も同様です。システムによって、ゼロまたはデフォルトのストレージのバイトサイズが決まります。

この情報を取得するためにファイルに対する読み取り権限は必要なく、リンクされたディレクトリに対する検索権限のみが必要です。

時系列で見ると次のようになります。

  • アイリックスstat(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
    

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

  • 牛に似た一種の栄養stat(2001); 2005年からBusyBoxに、2013年からstatToyboxに含まれていましたstat(両方ともGNUstatインターフェースをコピーしました)。

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

    -L(IRIXやとは逆の意味なので注意してくださいzsh stat。)

  • BSDstat(2002):

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

stat()または、一部のスクリプト言語の/ featuresを使用することもできます。たとえば、次のようになります。lstat()perl

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

AIXにも1つありますistat注文するstat()すべての情報(Symlinkではないため、シンボリックリンクには適用できません)をダンプし、lstat()この情報を後処理に使用できます。たとえば、次のようになります。

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

(@JeffSchallerに感謝します。詳細を把握するのに役立ちます。)。

存在するtcsh

@ size = -Z $file:q

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

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

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

$file-しかし、1つの問題は、このメソッドがorで始まると機能しないことですfind(たとえば!... ()。

バージョン4.9以降、この問題は引数の代わりにstdinを介してファイルパスを渡すことで解決できます。

printf '%s\0' "$file" |
  find -files0-from - -prune -printf '%s\n'

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

POSIXlyでは、次のことができます。

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

(後者が必要ないように-nヒントが必要ですが、一部のBSDでは必要であることがわかります。)-l

そして-Lシンボリックリンクを確認したら、同じ内容を追加してください。 5番目のフィールドはサイズではなくデバイスのキー番号ですが、これはデバイスファイルには適用されません。

ブロックデバイスの場合、stat()ゼロを返すシステムには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

今まで、私たちはただ考えました基本的なファイルに関連するデータです。これは、メタデータのサイズとそのファイルを保存するために必要なすべてのサポートインフラストラクチャを考慮しません。

返される別の inode プロパティstat()はですst_blocks。これは512バイト(HP/UXの1024)ファイルデータ(時にはLinuxのext4ファイルシステムの拡張属性などの一部のメタデータ)を格納するために使用されるブロック。これには、inode自体は含まれず、ファイルがリンクされているディレクトリのエントリも含まれません。

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

これは通常、duディスク使用量を報告するために使用されます。上記のほとんどのコマンドはこの情報を提供します。

  • POSIXLY_CORRECT=1 ls -sd -- "$file" | awk '{print $1; exit}'
  • POSIXLY_CORRECT=1 du -s -- "$file"(ファイルのディスク使用量を含むディレクトリには適用されません。)
  • 牛に似た一種の栄養find -- "$file" -printf '%b\n'
  • zstat -L +block -- $file
  • 牛に似た一種の栄養stat -c %b -- "$file"
  • BSDstat -f %b -- "$file"
  • perl -le 'print((lstat shift)[12])' -- "$file"

厳密に言えば、1970年代初頭のUNIXバージョンv1からv4までには1つのstatコマンドがありました。単にinodeから情報をダンプし、オプションは使用しません。 v5(1974)では消えたようです。おそらくls -l

関連情報