便携的方式来获取文件大小(以字节为单位)在shell中?
在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解决scheme。 只有输出格式在平台上可能不一致,因为可能会预留一些空格(Solaris就是这种情况)。
不要忽略inputredirect。 当文件作为parameter passing时,文件名将在字节计数后打印。
我担心它不适用于二进制文件,但它在Linux和Solaris上都可以正常工作。 你可以用wc -c < /usr/bin/wc
来试试。 此外,除非明确指定,POSIX实用程序保证处理二进制文件 。
我结束了写我自己的程序(真的很小),只显示大小。 更多信息在这里: http : //fwhacking.blogspot.com/2011/03/bfsize-print-file-size-in-bytes-and.html
在我看来,使用常见Linux工具的两个最干净的方法是:
$ stat -c %s /usr/bin/stat 50000 $ wc -c < /usr/bin/wc 36912
但我只是不想input参数或pipe道输出只是为了获得文件大小,所以我使用我自己的bfsize。
尽pipedu
通常会打印磁盘使用情况,而不是实际的数据大小,但是GNU coreutils du
可以按字节打印文件的“外观大小”
du -b FILE
但它不能在BSD,Solaris,MacOS下运行…
最后我决定使用ls和bash数组扩展:
TEMP=( $( ls -ln FILE ) ) SIZE=${TEMP[4]}
它不是很好,但至less它只有一个fork + execve,它不依赖于二级编程语言(perl / ruby / python / whatever)
跨平台最快的解决scheme(只对ls使用单个fork(),不会计算实际字符,不会产生不需要的awk,perl等)。
在MacOS,Linux上testing – 可能需要对Solaris进行较小的修改:
__ln=( $( ls -Lon "$1" ) ) __size=${__ln[3]} echo "Size is: $__size bytes"
如果需要,简化ls参数,并调整$ {__ ln [3]}中的偏移量。
注意:将遵循符号链接。
BSD拥有不同的GNU coreutils选项,但function类似。
stat -f %z <file name>
这适用于macOS (在10.12testing), FreeBSD , NetBSD和OpenBSD 。
您可以使用find
命令来获取一些文件(在这里提取临时文件)。 然后,可以使用du
命令,使用-h
开关以可读的forms获取每个文件的文件大小。
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~
你的第一个Perl例子对我来说看起来不合理。
正是出于这样的原因,我从编写shell脚本(使用bash / sh等)迁移到除了Perl中最平凡的脚本之外的所有东西。 我发现我不得不根据特定的需求来启动Perl,而且随着我越来越多的操作,我意识到使用Perl编写脚本可能是一个更强大的function(就语言和通过CPAN可用的各种库而言)和更有效的方式来实现我想要的。
请注意,其他shell脚本语言(例如python / ruby)无疑会有类似的function,您可能需要为您的目的进行评估。 我只讨论Perl,因为这是我使用和熟悉的语言。
那么du -s <file>
呢?
如果你使用GNU fileutils的find
:
size=$( find . -maxdepth 1 -type f -name filename -printf '%s' )
不幸的是, find
其他实现通常不支持-maxdepth
和-printf
。 例如Solaris和MacOS find
就是这种情况。
处理ls -n
输出时,作为不可移植的shell数组的替代,可以使用位置参数,这些参数构成唯一的数组,并且是标准shell中唯一的局部variables。 将函数中位置参数的覆盖包裹起来,将原始参数保存到脚本或函数中。
getsize() { set -- $(ls -dn "$1") && echo $5; } getsize FILE
这根据当前IFS
环境variables设置分割ln -dn
的输出,将其分配给位置参数并回显第五个。 -d
确保目录处理正确, -n
确保用户名和组名不需要parsing,与-l
不同。 而且,包含空格的用户名和组名在理论上可以打破预期的行结构; 他们通常被禁止,但这种可能性仍然使程序员停下来思考。
如果你的Solaris上有Perl,那就使用它。 否则,ls with awk是你的下一个最好的select,因为你没有stat或者你的find不是GNU find。
在我使用的Solaris中有一个技巧,如果你要求多个文件的大小,它只返回没有名字的总大小,所以包含一个空的文件,如/ dev / null作为第二个文件:
例如命令fileyouwant / dev / null
我不记得哪个大小的命令这对ls / wc / etc工作 – 不幸的是我没有一个solaris框来testing它。
在Linux上,你可以使用du -h $FILE
,在solaris上也能工作吗?
你试过了吗? awk'{print $ 1 * 1024}'。 这可能只是工作。