Portable way to get file size (in bytes) in shell?

2019-01-30 04:43发布

On Linux, I use stat --format="%s" FILE, but Solaris I have access to doesn't have stat command. What should I use then?

I'm writing Bash scripts, and can't really install any new software on the system.

I've considered already using:

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

or even:

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

But neither of these looks sensible - running Perl just to get file size? Or running 2 commands to do the same?

14条回答
Evening l夕情丶
2楼-- · 2019-01-30 04:55

Even though du usually prints disk usage and not actual data size, GNU coreutils du can print file's "apparent size" in bytes:

du -b FILE

But it won't work under BSD, Solaris, macOS, ...

查看更多
迷人小祖宗
3楼-- · 2019-01-30 04:57

You can use find command to get some set of files (here temp files are extracted). Then you can use du command to get the file size of each file in human readable form using -h switch.

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

OUTPUT:

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~
查看更多
干净又极端
4楼-- · 2019-01-30 04:58

Finally I decided to use ls, and bash array expansion:

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

it's not really nice, but at least it does only 1 fork+execve, and it doesn't rely on secondary programming language (perl/ruby/python/whatever)

查看更多
Emotional °昔
5楼-- · 2019-01-30 05:01

Cross platform fastest solution (only uses single fork() for ls, doesn't attempt to count actual characters, doesn't spawn unneeded awk, perl, etc).

Tested on MacOS, Linux - may require minor modification for Solaris:

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

If required, simplify ls arguments, and adjust offset in ${__ln[3]}.

Note: will follow symlinks.

查看更多
smile是对你的礼貌
6楼-- · 2019-01-30 05:03

If you use find from GNU fileutils:

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

Unfortunately, other implementations of find usually don't support -maxdepth, nor -printf. This is the case for e.g. Solaris and macOS find.

查看更多
来,给爷笑一个
7楼-- · 2019-01-30 05:04

wc -c < filename (short for word count, -c prints the byte count) is a portable, POSIX solution. Only the output format might not be uniform across platforms as some spaces may be prepended (which is the case for Solaris).

Do not omit the input redirection. When the file is passed as an argument, the file name is printed after the byte count.

I was worried it wouldn't work for binary files, but it works OK on both Linux and Solaris. You can try it with wc -c < /usr/bin/wc. Moreover, POSIX utilities are guaranteed to handle binary files, unless specified otherwise explicitly.

查看更多
登录 后发表回答