在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个命令来做同样的事情?
答案 0 :(得分:190)
wc -c < filename
(字数统计,-c
打印字节数)是一个可移植的POSIX解决方案。只有输出格式在不同平台上可能不一致,因为某些空格可能会被预先添加(Solaris就是这种情况)。
不要忽略输入重定向。当文件作为参数传递时,文件名将在字节计数后打印。
我担心它对二进制文件不起作用,但它在Linux和Solaris上都可以正常工作。您可以使用wc -c < /usr/bin/wc
进行尝试。此外,POSIX实用程序是guaranteed to handle binary files,除非另有明确说明。
答案 1 :(得分:35)
我最终编写了自己的程序(非常小)来显示大小。更多信息请访问: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
但我只是不想输入参数或管道输出只是为了获取文件大小,所以我使用自己的bfsize。
答案 2 :(得分:23)
即使du
通常打印磁盘使用情况而不是实际数据大小,GNU coreutils du
也可以打印文件的“表观大小”(以字节为单位):
du -b FILE
但它不适用于BSD,Solaris,macOS,......
答案 3 :(得分:13)
最后我决定使用ls和bash数组扩展:
TEMP=( $( ls -ln FILE ) )
SIZE=${TEMP[4]}
它不是很好,但至少它只有1个fork + execve,而且它不依赖于辅助编程语言(perl / ruby / python / whatever)
答案 4 :(得分:8)
跨平台最快的解决方案(仅使用单个fork()用于 ls ,不会尝试计算实际字符,也不会生成不需要的awk,perl等)。
在MacOS,Linux上测试 - 可能需要对Solaris进行少量修改:
__ln=( $( ls -Lon "$1" ) )
__size=${__ln[3]}
echo "Size is: $__size bytes"
如果需要,请简化 ls 参数,并调整$ {__ ln [3]}中的偏移量。
注意:将遵循符号链接。
答案 5 :(得分:7)
BSD的stat
具有与GNU coreutils不同的选项,但具有相似的功能。
stat -f %z <file name>
答案 6 :(得分:4)
当处理ls -n
输出时,作为易于携带的shell数组的替代,您可以使用位置参数,它们构成唯一的数组,并且是标准shell中唯一的局部变量。在函数中包含位置参数的覆盖,以保留脚本或函数的原始参数。
getsize() { set -- $(ls -dn "$1") && echo $5; }
getsize FILE
根据当前ln -dn
环境变量设置分割IFS
的输出,将其分配给位置参数并回显第五个。 -d
确保目录得到正确处理,-n
确保不需要解析用户名和组名,与-l
不同。此外,包含空格的用户名和组名理论上可以打破预期的行结构;他们通常不被允许,但这种可能性仍然让程序员停下来思考。
答案 7 :(得分:3)
如果您使用GNU fileutils中的find
:
size=$( find . -maxdepth 1 -type f -name filename -printf '%s' )
不幸的是,find
的其他实现通常不支持-maxdepth
,也不支持-printf
。这是例如Solaris和macOS find
。
答案 8 :(得分:3)
您可以使用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~
答案 9 :(得分:2)
你首先看到Perl的例子对我来说并不合理。
出于这样的原因,我从编写shell脚本(在bash / sh等中)迁移到编写Perl中除了最简单的脚本之外的所有脚本。我发现我必须针对特定要求启动Perl,而且随着我越来越多地这样做,我意识到在Perl中编写脚本可能更强大(就语言而言,可通过{提供的各种库) {3}})以及更有效的方式来实现我想要的目标。
请注意,其他shell脚本语言(例如python / ruby)无疑会有类似的功能,您可能需要根据自己的需要对其进行评估。我只讨论Perl,因为那是我使用的语言并且熟悉。
答案 10 :(得分:1)
我不知道 gnu gawk 的 filefuncs
扩展有多便携。基本语法是
$ time gawk -e '@load "filefuncs"; BEGIN {
fnL[1] = ARGV[ARGC-1];
fts(fnL, FTS_PHYSICAL, arr); print "";
for (fn0 in arr) {
print arr[fn0]["path"] \
" :: "arr[fn0]["stat"]["size"]; };
print ""; }' genieMV_204583_1.mp4
genieMV_204583_1.mp4 :: 259105690
real 0m0.013s
$ ls -Aln genieMV_204583_1.mp4
---------- 1 501 20 259105690 Jan 25 09:31
genieMV_204583_1.mp4
该语法允许一次检查多个文件。对于单个文件,它是
$ time gawk -e '@load "filefuncs"; BEGIN {
stat(ARGV[ARGC-1], arr);
printf("\n%s :: %s\n", arr["name"], \
arr["size"]); }' genieMV_204583_1.mp4
genieMV_204583_1.mp4 :: 259105690
real 0m0.013s
几乎没有任何增量节省。但不可否认,比直接上升略慢
$ time stat -f '%z' genieMV_204583_1.mp4
259105690
real 0m0.006s (BSD-stat)
$ time gstat -c '%s' genieMV_204583_1.mp4
259105690
real 0m0.009s (GNU-stat)
最后,一种将每个字节读入 awk 数组的简洁方法。此方法适用于二进制文件(正面或背面没有差异):
$ time mawk2 'BEGIN { RS = FS = "^$";
FILENAME = ARGV[ARGC-1]; getline;
print "\n" FILENAME " :: "length"\n"; }' genieMV_204583_1.mp4
genieMV_204583_1.mp4 :: 259105690
real 0m0.270s
$ time mawk2 'BEGIN { RS = FS = "^$";
} END { print "\n" FILENAME " :: " \
length "\n"; }' genieMV_204583_1.mp4
genieMV_204583_1.mp4 :: 259105690
real 0m0.269
但这不是最快的方法,因为您将所有内容都存储在 RAM 中。正常的 awk 范式在行上运行。问题是,对于像 mp4 这样的二进制文件,如果它们不完全以 \n
结尾,则 length + NR
方法的总和将多计一。下面的代码是一种通过明确使用最后一个 1 或 2 字节作为行分隔符 RS
的包罗万象的形式。
我发现使用 二进制文件 的 2-byte
方法要快得多,而 1-byte
方法是一个典型的以换行符结尾的文本文件 .对于二进制文件,1 字节的文件可能会导致行拆分过于频繁并减慢速度。
但我们在这里接近吹毛求疵,因为读取 1.83GB txt 文件的每个字节都需要 mawk2
,所以除非您正在处理大量数据,可以忽略不计。
尽管如此,正如其他人提到的,0.95 secs
仍然是迄今为止最快的,因为它是一个操作系统文件系统调用。
stat
(更新 mp4 的文件权限,因为 awk 方法需要它)
答案 11 :(得分:-3)
如果你的Solaris上有Perl,那么就使用它。否则,使用awk的ls是你的下一个最好的选择,因为你没有stat或你的发现不是GNU发现。
答案 12 :(得分:-3)
我使用的Solaris中有一个技巧,如果你要求多个文件的大小,它只返回没有名称的总大小 - 所以包括像/ dev / null这样的空文件作为第二个文件: / p>
例如 命令fileyouwant / dev / null
我无法记住哪个尺寸命令对ls / wc / etc有效 - 遗憾的是我没有solaris盒来测试它。
答案 13 :(得分:-4)
du -h $FILE
,这对solaris也有效吗?
答案 14 :(得分:-6)
你试过duks | awk'{print $ 1 * 1024}'。这可能会奏效。