如何使用Bash检查文件大小?


145

我有一个检查0大小的脚本,但是我认为必须有一种更简单的方法来检查文件大小。即file.txt通常为100k;如何使脚本检查其是否小于90k(包括0),并使其获得新的副本,因为在这种情况下文件已损坏。

我目前正在使用什么。

if [ -n file.txt ]
then
 echo "everything is good"
else
 mail -s "file.txt size is zero, please fix. " myemail@gmail.com < /dev/null
 # Grab wget as a fallback 
 wget -c https://www.server.org/file.txt -P /root/tmp --output-document=/root/tmp/file.txt
 mv -f /root/tmp/file.txt /var/www/file.txt
fi

Answers:


250

[ -n file.txt ]不检查其大小,而是检查字符串的file.txt长度是否为非零,因此它将始终成功。

如果要说“大小不为零”,则需要[ -s file.txt ]

要获取文件的大小,可以使用wc -c以字节为单位的大小(文件长度):

file=file.txt
minimumsize=90000
actualsize=$(wc -c <"$file")
if [ $actualsize -ge $minimumsize ]; then
    echo size is over $minimumsize bytes
else
    echo size is under $minimumsize bytes
fi

在这种情况下,听起来就是您想要的。

但是,仅供参考,如果您想知道文件正在使用多少磁盘空间,可以使用du -k以千字节为单位的大小(已使用的磁盘空间):

file=file.txt
minimumsize=90
actualsize=$(du -k "$file" | cut -f 1)
if [ $actualsize -ge $minimumsize ]; then
    echo size is over $minimumsize kilobytes
else
    echo size is under $minimumsize kilobytes
fi

如果您需要对输出格式的更多控制,也可以查看stat。在Linux上,您应使用stat -c '%s' file.txt,而在BSD / Mac OS X上,请使用stat -f '%z' file.txt


5
为什么要du -b "$file" | cut -f 1代替stat -c '%s' "$file"?还是stat --printf="%s" "$file"
mivk 2013年

1
仅因为它更便携。BSD和Linux stat 具有不同的标志。
Mikel 2013年

1
我必须对其进行修改... | cut -d' ' -f1才能使其在Ubuntu上运行。
Mikepote 2014年

8
使用wc -c < "$file"(请注意<),在这种情况下,您不需要| cut ...零件(如前所述,该零件在OSX上不起作用)。最小BLOCKSIZE的值du上OSX是512
mklement0 2014年

3
@PetriSirkkala在我的Linux系统上,wc -c <filename还使用fstatseek?请注意,这fstat需要一个fd,而不是一个路径名。
Mikel

24

令我惊讶的是,没有人提到stat要检查文件大小。某些方法绝对更好:-s如果您只想使用文件来查找文件是否为空,则比其他任何操作都容易。而且,如果您要查找一个大小的文件,那么find肯定是要走的路。

我也非常喜欢du以kb为单位的文件大小,但是对于字节,我会使用stat

size=$(stat -f%z $filename) # BSD stat

size=$(stat -c%s $filename) # GNU stat?

2
stat是个好主意,但在CentOS上这对我size=$(stat -c%s $filename)
Oz Solomon

2
不幸的是,GNU和BSD之间的区别是使这种替代方法的吸引力降低了。:(
lapo

1
如果文件稀疏,stat可能会产生误导。您可以使用stat报告的块来计算使用的空间。
Ajith Antony

@AjithAntony这是我没有想到的有趣观点。我可以看到在某些情况下stat正确的事情,而稀疏文件在大多数情况下并不相关,尽管当然不是全部。
Daniel C. Sobral

17

使用awk和双括号的替代解决方案:

FILENAME=file.txt
SIZE=$(du -sb $FILENAME | awk '{ print $1 }')

if ((SIZE<90000)) ; then 
    echo "less"; 
else 
    echo "not less"; 
fi

1
不错,但是不能在du不支持的OSX上使用-b。(这可能是有意识的款式选择,而只是提替代方案:您可以省略$前缀内(( ... ))引用变量时:((SIZE<90000))
mklement0

1
实际上,这是先前用户的编辑,他认为省略$
fstab

2
@fstab,您可以awk使用readbash内部命令)read SIZE _ <<<$(du -sb "$FILENAME")
忽略

13

如果您find使用以下语法,则可以使用它:

find -maxdepth 1 -name "file.txt" -size -90k

file.txt当且仅当大小file.txt小于90k时,这才输出到stdout 。script如果file.txt大小小于90k,则执行脚本:

find -maxdepth 1 -name "file.txt" -size -90k -exec script \;

3
+1,但也要使其在OSX上运行,您需要一个明确的目标目录参数,例如:find . -maxdepth 1 -name "file.txt" -size -90k
mklement0 2014年

8

如果只寻找文件大小:

$ cat $file | wc -c
> 203233

1
这可能是最短可行的答案,但也可能是最慢的答案。:)
SunSparc 2014年

2
是的,但肯定在经济上优越:工程时间成本>计算时间成本
BananaNeil 2014年

8
wc -c "$file"是在2011年(三年前)给出的答案。是的,wc -c "$file"有一个问题,它输出文件名以及字符数,因此早期的答案中添加了一个命令以区分出该数。但是wc -c < "$file",已解决了该问题,它在2014年5月作为评论添加了。您的答案与之相同,只不过它添加了“的无用用法cat。另外,除非有充分的理由,否则应引用所有shell变量引用。
G-Man说'Resstate Monica'2014/

1
您可以使用head -c代替cat.if [$(head -c 90000 $ file | wc -c)-lt 90000]来提高效率。然后回显“文件小于90k”;。在CentOS上进行了测试,因此它可能会或可能不会在BSD或OSX上运行。
凯文·基恩

@BananaNeil如何每20秒执行一次此过程,以便我可以检查文件大小的增量等等?
撒哈拉(Sahra)

6

这适用于linux和macos

function filesize
{
    local file=$1
    size=`stat -c%s $file 2>/dev/null` # linux
    if [ $? -eq 0 ]
    then
        echo $size
        return 0
    fi

    eval $(stat -s $file) # macos
    if [ $? -eq 0 ]
    then
        echo $st_size
        return 0
    fi

    return -1
}

5

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

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

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

$ strace wc --bytes $1 | wc
    307    3063   29091

$ strace du --bytes $1 | wc
    437    4376   41955

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

如果我正确理解,是否还应该通过管道重定向来完成测试?:strace du --bytes $1 2>&1 >/dev/null | wc 如果是这种情况,那么在ArchLinux的amd64体系结构(通常是所有产品的最新版本)上,我有45行du,46行stat,47行wc和72行find
VasiliNovikov

5
python -c 'import os; print (os.path.getsize("... filename ..."))'

可移植,各种python风格,避免stat方言的变化


4

为了在Linux和Mac OS X(以及可能的其他BSD)中获取文件大小,没有太多选项,这里建议的大多数选项只能在一个系统上使用。

鉴于f=/path/to/your/file

在Linux和Mac的Bash 中都有效的方法是:

size=$( perl -e 'print -s shift' "$f" )

要么

size=$( wc -c "$f" | awk '{print $1}' )

其他答案在Linux中可以正常工作,但在Mac中则不能:

  • du-b在Mac 中没有选项,并且BLOCKSIZE = 1技巧不起作用(“最小块大小为512”,导致错误的结果)

  • cut -d' ' -f1 不起作用,因为在Mac上,该数字可能是右对齐的,并在前面加了空格。

因此,如果您需要一些灵活的东西,它可以是perl-soperator,也可以通过wc -c管道连接到awk '{print $1}'(awk将忽略开头的空格)。

当然,对于其余的原始问题,请使用-lt(或-gt)运算符:

if [ $size -lt $your_wanted_size ]; then 等等


3
+1; 如果您知道仅在算术上下文中使用大小(忽略前导空格),则可以简化为size=$(wc -c < "$f")(请注意<,导致wc只报告数字)。重新比较:不要忘记更多的“害羞” if (( size < your_wanted_size )); then ...(还有[[ $size -lt $your_wanted_size ]])。
mklement0 2014年

3

根据gniourf_gniourf的回答,

find "file.txt" -size -90k

file.txt当且仅当大小file.txt小于90K时,才会写入stdout ;并且

找到“ file.txt” -size -90k -exec 命令 \;

command如果file.txt大小小于90K,将执行命令。我已经在Linux上进行了测试。来自find(1)

...命令行参数以下(在-H-L-P选项)要的名字取的文件或目录被检查,直至开头的第一个参数“ - ”,...

(强调)。


1
ls -l $file | awk '{print $6}'

假设ls命令报告列#6的文件大小


1

我会用du--threshold这个。不确定此选项是否在所有版本中均可用,du但已在GNU版本中实现。

引用du(1)的手册:

-t, --threshold=SIZE
       exclude entries smaller than SIZE if positive, or entries greater
       than SIZE if negative

这是我的解决方案,du --threshold=用于OP的用例:

THRESHOLD=90k
if [[ -z "$(du --threshold=${THRESHOLD} file.txt)" ]]; then
    mail -s "file.txt size is below ${THRESHOLD}, please fix. " myemail@gmail.com < /dev/null
    mv -f /root/tmp/file.txt /var/www/file.txt
fi

那好处,是du可以接受的已知格式的参数传递给选项-无论是人为的10K10MiB还是你觉得舒服什么都-你既然不需要格式/单元之间的手动转换du句柄。

作为参考,这SIZE是手册页中有关此参数的说明:

The SIZE argument is an integer and optional unit (example: 10K is 
10*1024). Units are K,M,G,T,P,E,Z,Y (powers of 1024) or KB,MB,... (powers
of 1000). Binary prefixes can be used, too: KiB=K, MiB=M, and so on.

+1出色的选择。不幸的是,我们中的一些人坚持使用du不支持它的旧版本。该--threshold选项已添加到2013年发布的 coreutils 8.21
阿米特·奈杜

1

好的,如果您使用的是Mac,请执行以下操作: stat -f %z "/Users/Example/config.log" 就是这样!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.