シェルでファイルサイズ(バイト単位)を取得するポータブルな方法はありますか?
質問
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 つのコマンドを実行しますか?
解決
wc -c < filename
(ワードカウントの短縮、-c
はバイトカウントを出力)は移植性のある、 POSIX ソリューション。一部のスペースが先頭に追加される場合があるため、出力形式のみがプラットフォーム間で統一されない場合があります(Solarisの場合)。
入力リダイレクトを省略しないでください。ファイルが引数として渡されると、ファイル名がバイトカウントの後に出力されます。
バイナリファイルでは動作しないのではないかと心配しましたが、LinuxとSolarisの両方で正常に動作します。 wc -c < /usr/bin/wc
で試すことができます。さらに、POSIXユーティリティは処理を保証します明示的に指定されていない限り、バイナリファイル。
他のヒント
サイズだけを表示する独自のプログラム(本当に小さい)を作成しました。詳細はこちら: 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を使用しています。
du
は通常、実際のデータサイズではなくディスク使用量を出力しますが、GNU coreutils <=>はファイルの<!> quot; apparent size <!> quot;を出力できます。バイト単位:
du -b FILE
しかし、BSD、Solaris、macOSなどでは動作しません...
最後に、ls と bash 配列拡張を使用することにしました。
TEMP=( $( ls -ln FILE ) )
SIZE=${TEMP[4]}
あまり良いものではありませんが、少なくとも 1 回の fork+execve だけを実行し、二次プログラミング言語 (perl/ruby/python/その他) に依存しません。
クロスプラットフォーム最速のソリューション( ls に単一のfork()のみを使用し、実際の文字をカウントしようとせず、不要なawk、perlなどを生成しません。)
MacOS、Linuxでテスト済み-Solarisの場合、若干の変更が必要な場合があります:
__ln=( $( ls -Lon "$1" ) )
__size=${__ln[3]}
echo "Size is: $__size bytes"
必要に応じて、 ls 引数を簡略化し、$ {__ ln [3]}のオフセットを調整します。
注:シンボリックリンクに従います。
BSDにはstat
があり、GNU coreutilsのものとは異なるオプションがありますが、機能は似ています。
stat -f %z <file name>
これは macOS で動作します(10.12でテスト済み)、 FreeBSD 、 NetBSD および OpenBSD 。
GNU fileutilsのfind
を使用する場合:
size=$( find . -maxdepth 1 -type f -name filename -printf '%s' )
残念ながら、他の-maxdepth
の実装は通常-printf
も<=>もサポートしていません。これは、たとえばSolarisおよびmacOS <=>。
移植性の低いシェル配列の代替としてls -n
出力を処理する場合、位置引数を使用できます。これは、唯一の配列を形成し、標準シェルの唯一のローカル変数です。関数内の位置引数の上書きをラップして、スクリプトまたは関数の元の引数を保持します。
getsize() { set -- $(ls -dn "$1") && echo $5; }
getsize FILE
これにより、現在のln -dn
環境変数設定に従ってIFS
の出力が分割され、位置引数に割り当てられ、5番目の引数がエコーされます。 -d
は、ディレクトリが適切に処理されることを保証し、-n
は、-l
とは異なり、ユーザー名とグループ名を解決する必要がないことを保証します。また、空白を含むユーザー名とグループ名は、理論的には予想される行構造を壊す可能性があります。通常は許可されませんが、この可能性により、プログラマーは停止して考えるようになります。
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~
最初の Perl の例は、私には不合理とは思えません。
このような理由から、私はシェル スクリプト (bash/sh など) を書くことから、最も簡単なスクリプトを除いてすべて Perl で書くことに移行しました。特定の要件のために Perl を起動する必要があることがわかり、それを繰り返すうちに、おそらく Perl でスクリプトを書く方が (言語と、 CPAN)そして私が望んでいたものを達成するためのより効率的な方法。
他のシェルスクリプト言語 (例:python/ruby) にも同様の機能があることは間違いなく、目的に応じてこれらを評価するとよいでしょう。Perl は私が使用しており、よく知っている言語であるため、Perl についてのみ説明します。
SolarisにPerlがある場合は、それを使用します。それ以外の場合、statがないか、findがGNU findではないため、lsとawkが次の最善策です。
私が使用したSolarisにはトリックがあります。複数のファイルのサイズを要求すると、名前のない合計サイズだけが返されます。したがって、2番目のファイルとして/ dev / nullなどの空のファイルを含めます。 / p>
eg コマンドファイルyouwant / dev / null
どのサイズのコマンドがls / wc / etcで機能するかを思い出せません-残念ながら、それをテストするためのソラリスボックスがありません。
Linuxではdu -h $FILE
を使用できますが、solarisでも動作しますか?
du -ksを試しましたか| awk '{print $ 1 * 1024}'。うまくいくかもしれません。