• du和ls的区别:如何正确计算文件大小


    上一篇文章写到的权限检查脚本,后来我又加入了 apk size 对比的功能,分享给组内同事使用后,暴露出一个问题:脚本输出的 apk size 和 Jenkins 出包信息以及电脑上显示的存储大小都有差异。那么,以何为准呢?

    以下是同事的提问及我的回复(已过滤敏感信息):

    使用脚本发现 APK SIZE 的检测结果,与在 Jenkins 出包信息有差异,且差异不小。 电脑上显示的存储大小也有差异,具体截图如下: 1、使用脚本检查两个版本结果为: 脚本中计算 apk size 的命令是:ls -s -k ls -- list directory contents -s Display the number of file system blocks actually used by each file, in units of 512 bytes, where partial units are rounded up to the next integer value. If the output is to a terminal, a total sum for all the file sizes is output on a line before the listing. The environment variable BLOCKSIZE overrides the unit size of 512 bytes. -k If the -s option is specified, print the file size allocation in kilobytes, not blocks. This option overrides the environment variable BLOCKSIZE. 如上所示,这个命令的作用是显示每个文件实际占有的文件系统中块(Block)的数量,每个块的大小是 512 字节。 确实,这个命令输出的信息有问题,在新脚本中已更正。具体的解释见第2&3条回复。

    2、查看 Jenkins 出包信息,大小差异为 0.25M: Jenkins 计算 apk size 的命令是:du -k du -- display disk usage statistics -k Display block counts in 1024-byte (1-Kbyte) blocks. du 是 Linux 系统中查看磁盘使用空间的命令,输出的是文件占有系统磁盘空间的块的数量(和上面提到的 ls -s 功能一样),加上参数 -k 可将块的数量转换成 1024 字节(1KB)的形式输出。 本来我最早写 apk size 对比的脚本时也打算用 du -k 的命令,结果发现这个命令在不同系统中会因为块的大小和文件占有磁盘空间大小的不同导致显示的 apk size 大小有差异。 后来转用了 ls -s -k 命令,结果发现,ls -s -k 踏入的是同样的坑(在不同系统中会因为块的大小和文件占有磁盘空间大小的不同导致显示的 apk size 大小有差异)。 说到这里,不得不提一下文件大小的两个概念: (1)文件占用磁盘空间的大小 (2)文件实际的大小 du -k 和 ls -s -k 属于第一种,计算的都是文件占用磁盘空间的大小。在电脑的文件系统中,存储是以块(Block)为单位的,不同的系统块的大小不一样,比如说 macOS 一个块的大小是 4096 字节。假设一个文件有 4097 字节,4097-4096=1,这个文件在占用了一个块之后,还有一个字节会占用到一个块,而块与块之间是不共享空间的,也就是说,剩下的 1 字节占用了一个块,这个块还空出 4095 字节,但是无法用于存储其他文件。所以,这个大小为 4097 字节的文件占用了 2 个块。而 du -k 和 ls -s -k 计算的正是每个文件占用块的多少。同理可得,其中必定有部分块是没有占满的,所以和实际的文件大小有差异。 那么,如何获得文件实际的大小呢?请看第三条回复

    3、查看电脑中存储信息,V122 出现了两个大小的值: 截图中,“通用”条目下的“大小”一行,15538958 字节表示的正是文件实际的大小。而括号中的“磁盘上的 16.4MB”,网上查到有人说是“压缩数据真正需要多少存储空间”(http://www.kbase101.com/question/47039.html),无法判断真假。 文件名右边的“15.5MB”,其实是 15538958bytes/1000/1000=15.538958MB,约等于 15.5MB。 文件的实际大小,可通过 ls -l 获得: 新的脚本已更新为获取文件的实际大小。

    脚本如下:

    #!/usr/bin/env bash
    
    #清空上次运行后产生的文件
    if [[ -f permission_old.txt ]]; then
        rm permission_old.txt permission_new.txt
    fi
    
    #读取apk文件地址
    read -p "请输入上个版本apk文件存放地址:" apk_old
    read -p "请输入最新版本apk文件存放地址:" apk_new
    
    #检查apk size
    b_size_old=`ls -l ${apk_old} | awk '{print $5}'`
    k_size_old=`awk 'BEGIN{printf "%.2f
    ", "'${b_size_old}'"/'1024'}'`
    m_size_old=`awk 'BEGIN{printf "%.2f
    ", "'${k_size_old}'"/'1024'}'`
    
    b_size_new=`ls -l ${apk_new} | awk '{print $5}'`
    k_size_new=`awk 'BEGIN{printf "%.2f
    ", "'${b_size_new}'"/'1024'}'`
    m_size_new=`awk 'BEGIN{printf "%.2f
    ", "'${k_size_new}'"/'1024'}'`
    
    #aapt命令解析apk,输出权限到文件
    aapt d badging ${apk_old} | grep "uses-permission:" | awk -F "'" '{print $2}' > permission_old.txt
    aapt d badging ${apk_new} | grep "uses-permission:" | awk -F "'" '{print $2}' > permission_new.txt
    
    #遍历新版本权限列表,对比旧版本权限列表是否相同,不同则为新增
    for x in $(cat permission_new.txt); do
        if cat permission_old.txt | grep ${x} > /dev/null; then
            echo "hello, world" > /dev/null
        else
            echo ${x} >> permission_increase.txt
        fi
    done
    
    #遍历旧版本权限列表,对比新版本权限列表是否相同,不同则为新减少
    for y in $(cat permission_old.txt); do
        if cat permission_new.txt | grep ${y} > /dev/null; then
            echo "hello, world" > /dev/null
        else
            echo ${y} >> permission_decrease.txt
        fi
    done
    
    #判断permission_increase.txt是否存在:存在,输出新增权限提醒;不存在,输出无新增权限
    if [[ ! -f permission_increase.txt ]]; then
        echo "无新增权限"
    else
        echo "新增权限:"
        cat permission_increase.txt
        #删除新增权限文件
        rm permission_increase.txt
    fi
    
    #判断permission_decrease.txt是否存在:存在,输出新减少权限提醒;不存在,输出无新减少权限
    if [[ ! -f permission_decrease.txt ]]; then
        echo "无新减少权限"
    else
        echo "新减少权限:"
        cat permission_decrease.txt
        #删除新减少权限文件
        rm permission_decrease.txt
    fi
    
    #输出apk size
    echo "------"
    echo "上个版本apk size: ${m_size_old}MB(${k_size_old}KB)"
    echo "最新版本apk size: ${m_size_new}MB(${k_size_new}KB)"
    #对比两个版本的apk size大小变化
    if [[ `echo "${m_size_new} > ${m_size_old}" | bc` -eq 1 ]]
    then
    exceeded_size=$(printf "%.2f" `echo "scale=2;${m_size_new}-${m_size_old}"|bc`)
    echo "最新版本比上个版本增加${exceeded_size}MB"
    else
    echo "apk size未增加"
    fi
    

    欢迎关注微信公众号"测试开发Stack"

  • 相关阅读:
    python的生成Jwt
    qq邮箱验证
    DJango反序列化器的参数效验
    python三元运算,继承,help函数 args
    python时间板块,计算取值,math函数
    No migrations to apply. django同步数据库失败
    redis理论部分
    Java入门——day1
    HBO《硅谷》中的二进制码
    复习总表现(每天记录一下)
  • 原文地址:https://www.cnblogs.com/liushengchieh/p/10820853.html
Copyright © 2020-2023  润新知