在 Linux 上,我使用 stat --format="%s" FILE,但是我可以访问的 索拉里斯机器没有 stat命令。那我该用什么?
stat --format="%s" FILE
stat
我正在编写 Bash 脚本,无法在系统上安装任何新软件。
我已经考虑过使用:
perl -e '@x=stat(shift);print $x[7]' FILE
甚至:
ls -nl FILE | awk '{print $5}'
但是这些看起来都不明智——运行 Perl只是为了得到文件大小?或者运行两个程序来做同样的事情?
您的第一个 Perl 示例在我看来并非不合理。
正是出于这样的原因,我从编写 shell 脚本(使用 Bash、 sh 等)转向编写佩尔最琐碎的脚本。我发现我不得不根据特定的需求启动 Perl,而且随着我越来越多地这样做,我意识到用 Perl 编写脚本可能是一种更强大的(就语言和通过 CPAN提供的大量库而言)和更有效的方法来实现我想要的。
请注意,其他 shell 脚本语言(例如 巨蟒和 露比)无疑也有类似的工具,您可能希望根据自己的需要对这些工具进行评估。我只讨论 Perl,因为它是我使用和熟悉的语言。
在 Linux 上你可以使用 du -h $FILE,也可以在 Solaris 上使用。
du -h $FILE
如果使用来自 GNU fileutils 的 find:
find
size=$( find . -maxdepth 1 -type f -name filename -printf '%s' )
遗憾的是,find的其他实现通常不支持 -maxdepth,也不支持 -printf。Solaris 和 macOS find就是这种情况。
-maxdepth
-printf
wc -c < filename(字计数的缩写,-c打印字节计数)是一种可移植的 POSIX解决方案。只有输出格式在不同平台之间可能不统一,因为可能预先添加了一些空格(Solaris 就是这种情况)。
wc -c < filename
-c
不要忽略输入重定向。当文件作为参数传递时,在字节计数之后打印文件名。
我担心它不能用于二进制文件,但它在 Linux 和 Solaris 上都能正常工作。你可以用 wc -c < /usr/bin/wc试试。此外,除非另外明确指定,否则 POSIX 实用程序是 保证处理二进制文件。
wc -c < /usr/bin/wc
如果您的 Solaris 上有 Perl,那么就使用它。否则,带有 AWK的 是的将是您的下一个最佳选择,因为您没有 立刻,或者您的 找到不是 GNU find。
试试 du -ks | awk '{print $1*1024}'也许能行。
du -ks | awk '{print $1*1024}'
最后,我决定使用 是的和 Bash 数组展开:
TEMP=( $( ls -ln FILE ) ) SIZE=${TEMP[4]}
虽然不是很好,但至少它只有一个 fork + Executive,而且不依赖于辅助编程语言(Perl、 露比、 巨蟒或其他)。
我在索拉里斯用过一个小把戏。如果你要求多个文件的大小,它只返回没有名称的总大小-所以包括一个空文件,如 /dev/null作为第二个文件:
比如说,
command fileyouwant /dev/null
我不记得这个命令适用于哪个大小-是的,WC,等等-不幸的是,我没有一个 Solaris 框来测试它。
最后我写了我自己的程序(真的很小)来显示大小。更多信息在 一个 href = “ http://fwhacking.blogspot.com/2011/03/bfsize-print-file-size-in-bytes-and.html”rel = “ nofollow noReferrer”> bfsize-print file size in bytes (and just that) 中。
在我看来,使用普通 Linux 工具最干净的两种方式是:
stat -c %s /usr/bin/stat 50000 wc -c < /usr/bin/wc 36912
但是我只是不想输入参数或管道输出只是为了得到一个文件大小,所以我使用我自己的 Bfsize。
尽管 du通常打印的是磁盘使用量而非实际数据大小,但 GNU核心工具组 du可以打印文件的“表观大小”(以字节为单位) :
du
du -b FILE
但是在 BSD、 索拉里斯、 MacOS等情况下不起作用。
跨平台的最快解决方案(它只对 是的使用一个 fork () ,不尝试计算实际字符数,不会产生不需要的 awk、 perl 等)。
它在 Mac OS X 和 Linux 上进行了测试,可能需要对 Solaris 进行一些小的修改:
__ln=( $( ls -Lon "$1" ) ) __size=${__ln[3]} echo "Size is: $__size bytes"
如果需要,简化 是的参数,并调整 ${ _ _ ln [3]}中的偏移量。
注意: 它将遵循符号链接。
您可以使用 find命令获取一些文件集(这里提取临时文件)。然后,您可以使用 du命令使用 -h开关以人类可读的形式获取每个文件的文件大小。
-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~
在处理 ls -n输出时,作为可移植性差的 shell 数组的替代方案,您可以使用位置参数,这些参数形成唯一的数组,并且是标准 shell 中唯一的局部变量。在函数中包装位置参数的覆盖,以保留脚本或函数的原始参数。
ls -n
getsize() { set -- $(ls -dn "$1") && echo $5; } getsize FILE
这将根据当前的 IFS环境变量设置分割 ln -dn的输出,将其分配给位置参数,并回应第五个参数。与 -l不同,-d确保正确处理目录,-n确保不需要解析用户名和组名。另外,包含空白的用户名和组名理论上可能会破坏预期的行结构; 它们通常是不允许的,但这种可能性仍然会让程序员停下来思考。
IFS
ln -dn
-l
-d
-n
BSD 系统具有与 GNU核心工具组不同的 stat选项,但具有类似的功能。
stat -f %z <file name>
这适用于 MacOS(在10.12上测试)、 FreeBSD、 NetBSD和 OpenBSD。
我不知道 GNU发呆的 filefuncs扩展有多便携
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
这几乎算不上任何增量节约,但不可否认的是,它略低于 stat的直线节约速度:
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的一种“全部捕获”形式。
\n
length + NR
RS
我发现对于 二进制文件使用 2字节方法要快得多,而 1字节方法是典型的以换行结束的 文本文件。对于二进制文件,1字节的文件最终可能会过于频繁地进行行分割,从而使其速度变慢。
但是我们接近于吹毛求疵,因为 mawk2只需要读入 1.83 GB的每一个字节。Txt 文件是 0.95秒,所以除非处理大量文件,否则它几乎可以忽略不计。
mawk2
尽管如此,正如其他人所提到的,stat仍然是最快的,因为它是一个 OS 文件系统调用。
time mawk2 'BEGIN { FS = "^$"; FILENAME = ARGV[ARGC-1]; cmd = "tail -c 2 \""FILENAME"\""; cmd | getline XRS; close(cmd); RS = ( length(XRS) == 1 ) ? ORS : XRS ; } { bytes += length } END { print FILENAME " :: " bytes + NR * length(RS) }' genieMV_204583_1.mp4 genieMV_204583_1.mp4 :: 259105690 real 0m0.092s m23lyricsRTM_dict_15.txt :: 1961512986 real 0m0.950s ls -AlnFT "${m3t}" genieMV_204583_1.mp4 -rw-r--r-- 1 501 20 1961512986 Mar 12 07:24:11 2021 m23lyricsRTM_dict_15.txt -r--r--r--@ 1 501 20 259105690 Jan 25 09:31:43 2021 genieMV_204583_1.mp4
(因为 AWK 方法需要,所以 MP4的文件权限被更新了。)
我会使用 是的来获得更好的速度,而不是使用 WC来读取管道中的所有流:
ls -l <filename> | cut -d ' ' -f5
这是以纯字节表示的
使用 —— b M或 —— b G标志输出兆字节或千兆字节(每个说法: 不便携 by < strong >@Andrew Henle 在评论中)。
顺便说一下,如果你打算去: 杜卡
du -b <filename> | cut -f -1
或者,通过 你好
du -h <filename> | awk '{print $1}'
或 立刻:
stat <filename> | grep Size: | awk '{print $2}'