如何在bash脚本中获取文件的大小?

如何将其分配给bash变量以便以后使用?

评论

stackoverflow.com/questions/5920333/如何检查要迁移的文件的LOL :-)

将其与pv和cat配对,以获取显示进度和ETA的复制命令:)

stat -c%s file.name

#1 楼

如果在GNU系统上,最好的选择是:

stat --printf="%s" file.any


来自于stat的数据:


%s总大小,以字节为单位


在bash脚本中:

#!/bin/bash
FILENAME=/home/heiko/dummy/packages.txt
FILESIZE=$(stat -c%s "$FILENAME")
echo "Size of $FILENAME = $FILESIZE bytes."


注意:有关如何在Mac OS X的终端中使用stat的信息,请参见@chbrown的回答。

评论


@ haunted85 stat是最简单的方法,假设您使用的是Linux或Cygwin(stat不是标准的)。 Eugéne建议的wc -c是可移植的。

–吉尔斯'所以-不再是邪恶的'
2011年7月14日在10:02

stat:非法选项-c

–尤利安·奥诺夫雷(Iulian Onofrei)
17年4月27日在13:42

stat --printf =“%s” file.txt在Debian Jessie上不输出任何内容...

– woohoo
17年4月29日在20:36

在MacOS上,此方法有效:stat -f%z myfile.tar

–ccpizza
18年5月6日在10:40

@woohoo您的提示将覆盖输出。 stat stat表示--printf省略了结尾的换行符。使用--format或-c查看输出。通过比较stat --printf =“%s”文件获得更多的见解。 xxd-到stat -c“%s”文件。 xxd-

–孙子
19年6月18日在11:06

#2 楼

file_size_kb=`du -k "$filename" | cut -f1`


使用stat的问题是它是GNU(Linux)扩展。 du -kcut -f1由POSIX指定,因此可移植到任何Unix系统。例如,Solaris附带bash但不附带stat。因此,这并非完全是假设。

ls也存在类似的问题,因为未指定输出的确切格式,因此无法移植其输出。 du -h还是GNU扩展。

如果可能,请坚持使用可移植的结构,这将使将来的人们的生活更轻松。也许是你自己的。

评论


du没有提供文件的大小,而是指示文件使用了多少空间,这有细微差别(通常du报告的大小是文件的大小四舍五入到最接近的块数,其中块通常为512B或1kB或4kB)。

–吉尔斯'所以-不再是邪恶的'
2011年7月14日10:00

@Gilles,稀疏文件(即文件中带有孔的文件)报告的长度小于长度。

– vonbrand
16年1月9日在22:03

用--bytes或-b而不是-k的形式应该是可接受的答案。

– Amedee Van Gasse
19年1月8日,12:56

@fralau:OP希望“将其分配给bash变量,以便他们以后可以使用它”,因此很有可能他们想要一个实际的数值,而不是人类可读的近似值。此外,-h是GNU扩展;这不是标准

– Nemo
19年4月1日在16:19

将du与--apparent-size标志一起使用将返回更精确的大小(如man上所述:打印表观大小,而不是磁盘使用情况;尽管表观大小通常较小,但由于孔(“稀疏” )文件,内部碎片,间接块等)

–Hugo H
19年8月6日在9:42



#3 楼

您还可以使用“字数统计”命令(wc):

wc -c "$filename" | awk '{print }'


wc的问题在于它将添加文件名并缩进输出。例如:

$ wc -c somefile.txt
    1160 somefile.txt


如果要避免链接完整的解释语言或流编辑器只是为了获得文件大小计数,只需重定向文件中的输入即可wc永远不会看到文件名:

wc -c < "$filename"


评论


wc -c <“ $ FILENAME”给出的大小没有其他内容,因此size = $(wc -c <“ $ FILENAME”)。

–吉尔斯'所以-不再是邪恶的'
2011年7月14日在9:58

还有一点:我刚刚进行了测试,并且wc -c <文件似乎非常快,至少在OS X上是如此。我猜想,如果仅指定-c,wc​​会绞尽脑汁尝试统计文件。

–爱德华·福克
16-4-4在16:29



@EdwardFalk:GNU wc -c使用fstat,但随后查找文件的倒数第二个块并读取最后一个st_blksize字节。显然这是因为,例如,Linux的/ proc和/ sys中的文件具有仅近似的统计数据大小,而wc希望报告实际大小,而不是统计数据报告的大小。我想wc -c报告的大小与wc不同会很奇怪,但是如果它是普通磁盘文件并且不在内存中,则不打算从文件中读取数据。更糟糕的是,近线磁带存储...

– Peter Cordes
17年4月12日在5:28

似乎printf仍然看到缩进,例如printf“ Size:$ size”-> size:<4个空格>54339。另一方面,echo忽略了空格。有什么办法可以使其一致吗?

–尤金·库拉布霍夫(Eugene Kulabuhov)
17年5月2日在12:43



@keithpjolley:通过调用fstat。尝试运行strace wc -c
– Nemo
19年1月8日在18:19



#4 楼

BSD(macOS)stat具有不同的格式参数标志和不同的字段说明符。来自man stat(1)



-f format:使用指定格式显示信息。有关有效格式的说明,请参见FORMATS部分。
... FORMATS部分...

z:文件大小(以字节为单位)。

所以现在一起:

stat -f%z myfile1.txt


注意:有关如何在GNU / Linux系统上使用stat命令的信息,请参见@ b01的答案。 :)

评论


请注意,这是仅BSD的解决方案。不幸的是,它不适用于GNU stat。

– joeytwiddle
19年11月28日在3:47

#5 楼

取决于您所指的大小。

size=$(wc -c < "$file")


将为您提供可以从文件读取的字节数。 IOW,它是文件内容的大小。但是,它将读取文件的内容(为优化起见,除非该文件是常规文件或在大多数wc实现中为常规文件的符号链接)。那可能会有副作用。例如,对于命名管道,已读取的内容将无法再读取,而对于/dev/zero/dev/random之类的无限大小的文件,则需要一段时间。这也意味着您需要对文件的read许可权,并且文件的最后访问时间戳可能会被更新。摆脱它们的一种方法是使用:

size=$(($(wc -c < "$file")))


,或者避免当wc不产生任何输出时(如无法打开文件):

size=$(($(wc -c < "$file") +0))


dash具有内置的yash(只要您启用它,您也可以将其调用为wc),这使其效率最高。对于该Shell中的常规文件。

各种系统都有一个名为ksh93的命令,该命令是wccommand /opt/ast/bin/wc系统调用的接口。该信息之一是stat属性。对于常规文件,这就是内容的大小(在没有错误的情况下可以从其中读取多少数据(这是大多数stat()实现优化使用的内容))。对于符号链接,这是目标路径的大小(以字节为单位)。对于命名管道,取决于系统,它可以是0或管道缓冲区中当前的字节数。对于块设备(在取决于系统的情况下)相同,您将获得0或基础存储的字节大小。

您不需要对该文件具有读取权限就可以获取该信息,而只需对其链接目录进行搜索即可。

按时间顺序,有: br />
IRIX lstat()(90年代):

stat -qLs -- "$file"


返回st_sizewc -c)的stat属性或:

相同,只是st_size是符号链接,在这种情况下,它是符号链接解析后的文件的$file


lstat() $file内置(现在也称为st_size)在zsh模块中(已装入stat)(1997年):

stat -s -- "$file"


或存储在变量中:

stat -L +size -- $file # st_size of file
stat +size -- $file    # after symlink resolution


显然,这是该shell中效率最高的。


GNU zstat(2001);自2005年以来也在BusyBox zsh/stat中(从GNU zmodload zsh/stat复制):

stat -L -A size +size -- $file


(请注意,与IRIX或stat stat相比,stat的含义相反。


BSD -L(2002):

stat -c %s -- "$file"  # st_size of file
stat -Lc %s -- "$file" # after symlink resolution



或者您可以使用某些脚本语言的zsh / stat函数,例如stat

stat -f %z -- "$file"  # st_size of file
stat -Lf %z -- "$file" # after symlink resolution


AIX还具有一个stat()命令,该命令将转储所有lstat()(不是perl,因此不适用于符号链接)信息,并且可以使用,例如:

perl -le 'print((lstat shift)[7])' -- "$file"


(感谢@JeffSchaller帮忙弄清细节)。

istat中:

LC_ALL=C istat "$file" | awk 'NR == 4 {print }'


(符号链接解析后的大小)

早在GNU引入stat()命令之前,GNU lstat()命令及其tcsh谓词就可以实现相同的功能(已经在1991):

@ size = -Z $file:q


不过,有一个问题是如果statfind开头或为-printf谓词(例如$file- ...),则不起作用。

获取find / !信息的标准命令是(

POSIXly,您可以执行以下操作:在符号链接解析之后。尽管设备文件的第5个字段是设备主编号而不是大小,但这不适用于设备文件。块设备的大小。例如,Linux具有stat()lstat(),并且大多数Linux发行版现在都附带有可以使用它的ls命令:

find -- "$file" -prune -printf '%s\n'    # st_size of file
find -L -- "$file" -prune -printf '%s\n' # after symlink resolution


但是,您需要具有读取权限设备文件。通常可以通过其他方式得出尺寸。例如(仍然在Linux上):

LC_ALL=C ls -dn -- "$file" | awk '{print ; exit}'


除空设备外应该可以使用。

一种适用于所有可搜索文件的方法(因此包括常规文件,大多数块设备和某些字符设备)是打开文件并查找到末尾:



使用-L(在加载stat()模块之后):

blockdev --getsize64 -- "$device_file"



st_size一起:

lsblk -bdno size -- "$device_file"




{sysseek -w end 0 && size=$((systell(0)))} < $file



带有BLKGETSIZE64

< "$file" <#((size=EOF))



对于命名管道,我们已经看到一些系统(AIX至少Solaris,HP / UX)在ioctl()blockdev中使管道缓冲区中的数据量可用。某些(例如Linux或FreeBSD)没有。

至少在Linux上,打开管道后可以使用zsh zsh/system(在读写模式下避免挂起): >
{ size=$(<#((EOF))); } < "$file"


但是请注意,虽然它不读取管道的内容,但仅在此处打开命名管道仍会产生副作用。我们正在使用ksh93首先检查某些进程是否已经打开管道来缓解这种情况,但这并不是万无一失的,因为perl可能无法检查所有进程。

现在,到目前为止,我们仅一直在考虑与文件关联的主要数据的大小。这没有考虑元数据的大小以及存储该文件所需的所有支持基础结构。

stat()返回的另一个inode属性是st_size。这就是用于存储文件数据(有时是某些元数据,例如Linux上ext4文件系统上的扩展属性)的512字节块的数量。这不包括索引节点本身,也不包括文件链接到的目录中的条目。

大小和磁盘使用情况不一定与压缩,稀疏(有时是一些元数据),额外的基础结构紧密相关。像某些文件系统中的间接块会对后者产生影响。

FIONREAD通常用来报告磁盘使用情况。上面列出的大多数命令都可以为您提供该信息。


ioctl()

fuser(不适用于包含磁盘使用情况的目录)文件中的文件。)
GNU fuser

stat()
GNU st_blocks

BSD du

POSIXLY_CORRECT=1 ls -sd -- "$file" | awk '{print ; exit}'


评论


显然是最全面,最有用的答案。谢谢。我可以使用它来使用BSD和GNU统计信息创建跨平台的bash脚本

–寡核苷酸
17年1月11日,12:50

有趣的事实:GNU coreutils wc -c使用fstat,但随后读取最后一个st_blksize字节。显然这是因为,例如,Linux的/ proc和/ sys中的文件具有仅近似的统计数据大小。这对于正确性有好处,但如果文件的末尾位于磁盘而不是内存中,则不好(特别是如果在循环中用于许多文件)。如果文件迁移到近线磁带存储,例如FUSE透明解压缩文件系统。

– Peter Cordes
17年4月12日在5:48



这也不会ls -go文件| awk'{print $ 3}'

–史蒂芬·潘妮(Steven Penny)
18年2月8日在13:00

@StevenPenny -go将是SysV,它们将无法在BSD(POSIX中的可选(XSI))上运行。您还需要ls -god文件| awk'{print $ 3;退出}”(-d使其在目录上工作,退出以在目标中带有换行符的符号链接)。设备文件的问题也仍然存在。

–StéphaneChazelas
18年2月8日在22:31

@αғsнιηUnix API在文本文件和二进制文件之间没有区别。都是字节序列。某些应用程序可能希望将这些字节解释为文本,但显然不希望wc -c报告字节数。

–StéphaneChazelas
19-2-17在8:41



#6 楼

该脚本结合了多种计算文件大小的方法:

(
  du --apparent-size --block-size=1 "$file" 2>/dev/null ||
  gdu --apparent-size --block-size=1 "$file" 2>/dev/null ||
  find "$file" -printf "%s" 2>/dev/null ||
  gfind "$file" -printf "%s" 2>/dev/null ||
  stat --printf="%s" "$file" 2>/dev/null ||
  stat -f%z "$file" 2>/dev/null ||
  wc -c <"$file" 2>/dev/null
) | awk '{print }'


该脚本可在许多Unix系统上运行,包括Linux,BSD,OSX,Solaris,SunOS等。

文件大小显示字节数。它是表观大小,即文件在典型磁盘上使用的字节,没有特殊压缩,特殊稀疏区域或未分配的块等。

此脚本的生产版本具有更多帮助和更多选项在这里:
https://github.com/SixArm/file-size

#7 楼

stat似乎使用最少的系统调用来执行此操作:

$ set debian-live-8.2.0-amd64-xfce-desktop.iso

$ strace stat --format %s  | wc
    282    2795   27364

$ strace wc --bytes  | wc
    307    3063   29091

$ strace du --bytes  | wc
    437    4376   41955

$ strace find  -printf %s | wc
    604    6061   64793


#8 楼

ls -l filename将为您提供有关文件的许多信息,包括文件大小,权限和所有者。

文件大小在第五栏中,以字节显示。在下面的示例中,文件大小不到2KB:

-rw-r--r-- 1 user owner 1985 2011-07-12 16:48 index.php


编辑:显然,它不如stat命令可靠。

评论


我认为ls -l和stat命令都提供可靠的大小信息。我没有找到任何相反的参考。 ls -s将给出块的大小。

–dabest1
2012年12月31日在22:23



@ dabest1从某种意义上说在另一个unix中,它们的输出可能不同(在某些unix中是不同的),这是不可靠的。

– Eugene Bujak
2014年10月2日14:39

是的,IIRC,Solaris默认情况下不显示组名称,从而导致输出中的列减少。

–爱德华·福克
16-4-4在16:31



由于大小是纯数字的,周围是空格,而日期年份是纯数字,因此格式已定义,因此无论该组是否存在,都可以使用正则表达式将用户+所有者视为一个字段。 (供读者练习!)

– MikeW
17-2-21在15:31

#9 楼

du filename会以字节为单位告诉您磁盘的使用情况。

我更喜欢du -h filename,它以可读取的格式为您提供了大小。

评论


that或stat -c“%s”;)

–c00kiemon5ter
2011年7月13日在16:29

这种du的打印输出大小为1024字节,而不是简单的字节计数。

– Peter Lyons
2015年9月17日下午5:10

请注意,标准du以512字节为单位给出输出。除非在其环境中使用POSIXLY_CORRECT调用,否则GNU du会使用kibibytes。

–StéphaneChazelas
16年11月8日在15:01

对于目录类型的文件,这将提供目录的磁盘使用情况,还可以(递归地)提供其中的所有其他文件的磁盘使用情况。

–StéphaneChazelas
16年11月8日在15:02

#10 楼

在可以委托给您的Shell脚本中创建小的实用程序函数。

示例

#! /bin/sh -
# vim: set ft=sh

# size utility that works on GNU and BSD systems
size(){
    case $(uname) in
        (Darwin | *BSD*)
            stat -Lf %z -- "";;
        (*) stat -c %s -- ""
    esac
}

for f do
    printf '%s\n' "$f : $(gzip < "$f" | wc -c) bytes (versus $(size "$f") bytes)"
done


基于@StéphaneChazelas的回答中的信息。

评论


另请参见gzip -v <文件> / dev / null以检查文件的可压缩性。

–StéphaneChazelas
17年1月11日在14:36

@StéphaneChazelas不知道我是否认为这是一种改进。这些案例陈述很容易让菜鸟失望。我当然从来都不记得如何正确对待它们:-)自从您这样做以来,case语句在本质上更可移植吗?我看到有两种以上情况的要点,但否则... +

–寡核苷酸
17年1月11日在16:48



我想这也是一个问题,但这是您要使用case语句的典型情况。 case是Bourne / POSIX构造来进行模式匹配。 [[...]]仅限于ksh / bash / zsh(带有变体)。

–StéphaneChazelas
17年1月11日在16:55

#11 楼

我找到了AWK 1班轮,它有一个错误,但我已修复。我还在TeraBytes之后添加了PetaBytes。

FILE_SIZE=234234 # FILESIZE IN BYTES
FILE_SIZE=$(echo "${FILE_SIZE}" | awk '{ split( "B KB MB GB TB PB" , v ); s=1; while( >1024 ){ /=1024; s++ } printf "%.2f %s", , v[s] }')


考虑到不是每个系统上的统计信息,您几乎总是可以使用AWK解决方案。例; Raspberry Pi没有统计信息,但确实有awk。

评论


完全不是OP的要求,而是很好的一小部分工作。

–辛德拉巴
18年6月10日在5:48

#12 楼

我自己喜欢wc选项。与“ bc”配对,您可以将小数位数尽可能多地取整。

我想改进一个脚本,使aws的“文件大小”列变awk -alh'命令。我不只是想要整数文件大小,而且两个小数点似乎也适合,因此在阅读了此讨论之后,我想到了下面的代码。

如果您将其包含在脚本中,我建议在分号前加分行。图片文件的长度。”我在imagemagick中对文件进行了迁移之后,在GUI jpeg查看器中打开或重新加载图片之前使用它。它从已经提供和讨论的内容中借鉴了很多东西。所以我就把它留在那里。

BZT

评论


我更喜欢使用“ stat”或“ ls”。通常,我不喜欢使用“ wc”来获取文件大小,因为它会物理读取整个文件。如果您有很多文件,或者特别大的文件,这可能会花费很多时间。但是您的解决方案很有创意... + 1。

–凯文·费根(Kevin Fegan)
2013年12月9日19:18

我同意在文件大小上使用“ stat”而不是“ wc”的观点,但是,如果使用“ wc -c”,则不会读取任何数据;而是使用lseek来计算文件中的字节数。 lingrok.org/xref/coreutils/src/wc.c#228

–bbaja42
2014年12月14日14:38

@ bbaja42:请注意,如果stat.st_size仅是近似值(例如对于Linux / proc和/ sys文件),GNU Coreutils wc确实会读取文件的最后一块。我想他们决定在添加以下几行逻辑后,决定不使主要意见变得更加复杂:lingrok.org/xref/coreutils/src/wc.c#246

– Peter Cordes
17年4月12日在5:53

#13 楼

最快最简单的(IMO)方法是:

bash_var=$(stat -c %s /path/to/filename)


评论


然后对提及stat的一个或多个现有答案进行投票;无需再次重复...

– Jeff Schaller♦
18年11月21日在1:16

@JeffSchaller我只是根据您的指示对Stephane的回答表示支持。我认为这太复杂了。这就是为什么我将这个简单的答案发布给志趣相投的人的原因。

–WinEunuuchs2Unix
18年11月21日在1:21

谢谢;仅仅是“统计”答案的第六个实例并不能简化此问答,而是希望新读者问自己“此答案与其他答案有何不同?”导致更多的混乱而不是更少。

– Jeff Schaller♦
18年11月21日在1:32

我猜@JeffSchaller。但是我可能会抱怨很多du和wc的答案,这些答案在现实生活中绝对不要这样做。今晚,我只是在现实生活中使用了我的答案,并认为值得分享。我想我们所有人都耸耸肩。

–WinEunuuchs2Unix
18年11月21日在1:36