上一篇文章写到的权限检查脚本,后来我又加入了 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\n", "'${b_size_old}'"/'1024'}'`
m_size_old=`awk 'BEGIN{printf "%.2f\n", "'${k_size_old}'"/'1024'}'` b_size_new=`ls -l ${apk_new} | awk '{print $5}'`
k_size_new=`awk 'BEGIN{printf "%.2f\n", "'${b_size_new}'"/'1024'}'`
m_size_new=`awk 'BEGIN{printf "%.2f\n", "'${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"

du和ls的区别:如何正确计算文件大小的更多相关文章

  1. 转 由一次磁盘告警引发的血案:du 和 ls 的区别

    如果你完全不明白或者完全明白图片含义, 那么你不用继续往下看了. 否则, 这篇文章也许正是你需要的. 背景 确切地说,不是收到的自动告警短信或者邮件告诉我某机器上的磁盘满了,而是某同学人肉发现该机器写 ...

  2. linux du与ls查看文件大小时的区别

    du和ls查看文件大小的区别 du == disk usage (磁盘使用量,占用的磁盘空间)du 的基本使用du -s     #s参数是可以统计占硬盘空间大小的如 du -skh web-k或-- ...

  3. linux:ls、ls -l、ls -al区别 示例

    linux:ls.ls -l.ls -al区别 示例 比如test文件夹下有一个test文件.一个.文件夹.一个..文件夹. 则,执行三个命令后,显示效果如下: [root@linuxserver t ...

  4. 网络基础、ftp任务(进度条、计算文件大小、断点续传、搭建框架示例)

    一.网络基础 1.端口,是什么?为什么要有端口? 端口是为了将同一个电脑上的不同程序进行隔离. IP是找电脑:端口是找电脑上的应用程序: 端口范围:1 – 65535 :    1 - 1024 不要 ...

  5. php 计算文件大小

    计算文件大小 主要计算文件的 size 大小,默认的为Bytes的,所以运用三元运算符,来进行转换. 转换成 Bytes->KB->MB->GB /** * @param $size ...

  6. 正确计算linux系统内存使用率

    参考:https://blog.gesha.net/archives/406/ 图中的例子很典型,就是:多数的linux系统在free命令后会发现free(剩余)的内存很少,而自己又没有开过多的程序或 ...

  7. linux中du与df的区别和联系

    1,两者区别 du,disk usage,是通过搜索文件来计算每个文件的大小然后累加,du能看到的文件只是一些当前存在 的,没有被删除的.他计算的大小就是当前他认为存在的所有文件大小的累加和. df, ...

  8. AC、HC、AHC、ACT、LS的区别

    http://forum.eet-cn.com/thread!printPreview.jspa?threadID=1200029698&start=0 以245为例,74AC245.74HC ...

  9. ScrollView与ListView合用(正确计算Listview的高度)的问题解决

    最近做项目中用到ScrollView和ListView一起使用的问题,显示的时候ListView不能完全正确的显示,查了好多资料终于成功解决:   首先,ListView不能直接用,要自定义一个,然后 ...

随机推荐

  1. PMP132种工具与技术

    <PMBOK ® 指南>第六版中共包括 132 种工具与技术 <PMBOK ® 指南>使用了以下工具与技术分组:1.数据收集技术.用于从各种渠道收集数据与信息.共有9 种数据收 ...

  2. C# 刷遍 Leetcode 面试题系列连载(3): No.728 - 自除数

    前文传送门: C#刷遍Leetcode面试题系列连载(1) - 入门与工具简介 C#刷遍Leetcode面试题系列连载(2): No.38 - 报数 系列教程索引 传送门:https://enjoy2 ...

  3. 简单ALV得演示(用到了ALV可编辑及保存后修改数据库)

    *&---------------------------------------------------------------------* *& Report YPMRP010_ ...

  4. WPF ListView ,XML

    <?xml version="1.0" encoding="utf-8" ?><PersonList> <Person Id=&q ...

  5. Django类

    django 1.中间件   中间件一般做认证或批量请求处理,django中的中间件,其实是一个类,在请求和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法, 如请求过来 执行p ...

  6. C++学习03_引用

    基本使用 C++提供了给变量命名的机制,就是引用(Reference).引用是一种复合类型. //语法 数据类型 &name=data 注意,引用在定义时需要添加&,在使用时不能添加& ...

  7. @RequestMapping和@GetMapping和PostMapping

    简介 - @GetMapping是一个组合注解,是@RequestMapping(method = RequestMethod.GET)的缩写.该注解将HTTP Get 映射到 特定的处理方法上. - ...

  8. Ubuntu下搭建Kubernetes集群(4)--部署K8S Dashboard

    K8S Dashboard是官方的一个基于WEB的用户界面,专门用来管理K8S集群,并可展示集群的状态.K8S集群安装好后默认没有包含Dashboard,我们需要额外创建它. 首先我们执行命令: wg ...

  9. MacOS上传文件到windows ftp时链接文件不见了

    最近打包遇到了一个问题,打包完MAC的sdk包后,得到的是一个framework的文件夹,我们需要将这个framework传到ftp服务器上,另外,还要把这个文件夹下的Release文件夹里的文件替换 ...

  10. 201871010132-张潇潇-《面向对象程序设计(java)》第十周总结

    项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...