du和ls的區別:如何正確計算文件大小

上一篇文章寫到的權限檢查腳本,後來我又加入了 apk size 對比的功能,分享給組內同事使用後,暴露出一個問題:腳本輸出的 apk size 和 Jenkins 出包信息以及電腦上顯示的存儲大小都有差別。那麼,以何爲準呢?html

如下是同事的提問及個人回覆(已過濾敏感信息):bash

使用腳本發現 APK SIZE 的檢測結果,與在 Jenkins 出包信息有差別,且差別不小。
電腦上顯示的存儲大小也有差別,具體截圖以下:
一、使用腳本檢查兩個版本結果爲:

腳本中計算 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條回覆。微信

二、查看 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 計算的正是每一個文件佔用塊的多少。同理可得,其中一定有部分塊是沒有佔滿的,因此和實際的文件大小有差別。
那麼,如何得到文件實際的大小呢?請看第三條回覆ide

三、查看電腦中存儲信息,V122 出現了兩個大小的值:

截圖中,「通用」條目下的「大小」一行,15538958 字節表示的正是文件實際的大小。而括號中的「磁盤上的 16.4MB」,網上查到有人說是「壓縮數據真正須要多少存儲空間」(http://www.kbase101.com/question/47039.html),沒法判斷真假。
文件名右邊的「15.5MB」,實際上是 15538958bytes/1000/1000=15.538958MB,約等於 15.5MB。
文件的實際大小,可經過 ls -l 得到:

新的腳本已更新爲獲取文件的實際大小。測試

腳本以下:code

#!/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"htm

相關文章
相關標籤/搜索