web-dev-qa-db-ja.com

シェルでファイルサイズ(バイト単位)を取得するポータブルな方法ですか?

Linuxでは、stat --format="%s" FILEを使用しますが、アクセスできるSolarisにはstatコマンドがありません。それから何を使うべきですか?

Bashスクリプトを書いていますが、システムに新しいソフトウェアを実際にインストールすることはできません。

私はすでに使用することを検討しました:

Perl -e '@x=stat(shift);print $x[7]' FILE

あるいは:

ls -nl FILE | awk '{print $5}'

しかし、これらのどちらも賢明ではありません-ファイルサイズを取得するためだけにPerlを実行していますか?または2つのコマンドを実行して同じことをしますか?

106
user80168

wc -c < filename(ワードカウントの短縮、-cはバイトカウントを出力)は移植性があり、 POSIX ソリューションです。一部のスペースが先頭に追加される場合があるため、出力形式のみがプラットフォーム間で統一されない場合があります(Solarisの場合)。

入力リダイレクトを省略しないでください。ファイルが引数として渡されると、ファイル名はバイトカウントの後に出力されます。

バイナリファイルでは動作しないのではないかと心配しましたが、LinuxとSolarisの両方で正常に動作します。 wc -c < /usr/bin/wcで試すことができます。さらに、明示的に指定されない限り、POSIXユーティリティは バイナリファイルの処理を保証 です。

195
Carl Smotricz

最終的に、サイズだけを表示する独自のプログラム(本当に小さい)を作成しました。詳細はこちら: http://fwhacking.blogspot.com/2011/03/bfsize-print-file-size-in-bytes-and.html

私の意見では、一般的なLinuxツールで最もクリーンな2つの方法は次のとおりです。

$ stat -c %s /usr/bin/stat
50000

$ wc -c < /usr/bin/wc
36912

ただし、ファイルサイズを取得するためだけにパラメーターを入力したり、出力をパイプしたりする必要はないため、独自のbfsizeを使用しています。

35
fwhacking

duは通常、実際のデータサイズではなくディスク使用量を出力しますが、GNU coreutils duはファイルの「見かけのサイズ」をバイト単位で出力できます。

du -b FILE

しかし、BSD、Solaris、macOSなどでは動作しません...

23
fwhacking

最後に、lsとbash配列展開を使用することにしました。

TEMP=( $( ls -ln FILE ) )
SIZE=${TEMP[4]}

それは本当に素敵ではありませんが、少なくとも1つのfork + execveのみを実行し、セカンダリプログラミング言語(Perl/Ruby/python/whatever)に依存しません

13
user80168

クロスプラットフォーム最速のソリューション(lsに単一のfork()のみを使用し、実際の文字をカウントしようとせず、不要なawk、Perlなどを生成しません)。

MacOS、Linuxでテスト済み-Solarisのマイナーな修正が必要な場合があります。

__ln=( $( ls -Lon "$1" ) )
__size=${__ln[3]}
echo "Size is: $__size bytes"

必要に応じて、ls引数を簡略化し、$ {__ ln [3]}のオフセットを調整します。

注:シンボリックリンクに従います。

8
Orwellophile

BSDには、GNU coreutilsのオプションとは異なるオプションを持つstatがありますが、機能は似ています。

stat -f %z <file name> 

これは macOS (10.12でテスト済み)、 FreeBSDNetBSD および OpenBSD で動作します。

7
user7504315

GNU fileutilsからfindを使用する場合:

size=$( find . -maxdepth 1 -type f -name filename -printf '%s' )

残念ながら、findの他の実装は通常、-maxdepth-printfもサポートしていません。これは、たとえばSolarisおよびmacOS find

4

移植性の低いシェル配列の代替としてls -n出力を処理するとき、位置引数を使用できます。これは、唯一の配列を形成し、標準シェルの唯一のローカル変数です。関数内の位置引数の上書きをラップして、スクリプトまたは関数の元の引数を保持します。

getsize() { set -- $(ls -dn "$1") && echo $5; }
getsize FILE

これは、現在のIFS環境変数設定に従ってln -dnの出力を分割し、それを位置引数に割り当て、5番目の引数をエコーし​​ます。 -dは、-nとは異なり、ディレクトリが適切に処理されることを保証し、-lは、ユーザー名とグループ名を解決する必要がないことを保証します。また、空白を含むユーザーおよびグループ名は、理論的には予想される行構造を壊す可能性があります。通常は許可されていませんが、この可能性により、プログラマは停止して考えるようになります。

4
Richard

findコマンドを使用して、ファイルのセットを取得できます(ここでは一時ファイルが抽出されます)。その後、duコマンドを使用して、-hスイッチを使用して、人間が読める形式で各ファイルのファイルサイズを取得できます。

find $HOME -type f -name "*~" -exec du -h {} \;

出力:

4.0K    /home/turing/Desktop/JavaExmp/TwoButtons.Java~
4.0K    /home/turing/Desktop/JavaExmp/MyDrawPanel.Java~
4.0K    /home/turing/Desktop/JavaExmp/Instream.Java~
4.0K    /home/turing/Desktop/JavaExmp/RandomDemo.Java~
4.0K    /home/turing/Desktop/JavaExmp/Buff.Java~
4.0K    /home/turing/Desktop/JavaExmp/SimpleGui2.Java~
3
Abhishek Singh

最初のPerlの例は、私には不合理に見えません。

このような理由により、シェルスクリプト(bash/shなど)の記述からPerlで最も些細なスクリプトを除くすべての記述に移行しました。特定の要件のためにPerlを起動する必要があることがわかりましたが、それを行うたびに、Perlでスクリプトを記述する方がおそらくより強力であることに気付きました(言語と- CPAN )と私が望んでいたものを達成するためのより効率的な方法。

他のシェルスクリプト言語(たとえば、python/Ruby)に同様の機能があることは間違いないため、目的に応じてこれらを評価することをお勧めします。 Perlは私が使用している言語であり、慣れ親しんでいるため、Perlについてのみ説明します。

2
Brian Agnew