最近,數據遷移差點讓我抓狂


本文微信公眾號「AndroidTraveler」首發。

背景

最近,要重裝 macOS,所以需要拷貝數據進行備份。

而這個備份過程差點讓我抓狂,速度超級慢,等待時間很是煎熬。

分析

這邊看了一下,主要是因為文件過多對數據遷移速度造成了較大的影響。

大家知道,我們用 AndroidStudio 新建一個 HelloWorld 項目,系統會自動幫我們生成很多文件。

這邊建了一個,並查看了文件(包括目錄)數目,有 85 個文件,這還是最簡單的項目。

假設一般的項目平均 1000 個文件,有 100 個項目則文件數目達到 10 萬級別。(PS:我遇到過一個項目就高達 5 萬多個文件數目的)

如果你直接拷貝的話,那么耗時是非常長的,尤其是對於機械硬盤而言。

那么我們能否壓縮一下呢?

這么大量的文件,如果你一次性全部壓縮成一個文件,那么耗時也是比較大的。

因此這邊就想可否每個項目單獨壓縮,這樣耗時是不是就相對要少一些呢?

但是直接在 mac 上面右鍵並沒有批量壓縮選項。

選擇多個系統會以為你要把多個目錄壓縮成一個文件。

我們知道,壓縮文件可以使用命令行。

所以我們可以通過腳本來實現批處理壓縮文件。

實戰

那下面我們就一步一步來完成批處理壓縮腳本的編寫。

Step 1: 創建並運行腳本

我們假設創建的腳本名字為 batch_zip.sh

在終端上執行下面命令:

touch batch_zip.sh;chmod u+x batch_zip.sh

第一條命令是創建 batch_zip.sh 文件,第二個命令是為該文件增加可執行權限,因為我們的腳本最后是需要運行的。

如果你是直接拷貝我文末鏈接上的腳本文件,你下載到本地只需要執行第二條命令即可。

Step 2: 熟悉壓縮命令

首先我們需要了解壓縮命令。最基本的壓縮命令如下:

zip 壓縮后文件.zip 壓縮前文件

由於我們有遞歸壓縮需求,因此需要添加 -r 選項。

另外壓縮過程默認會顯示壓縮詳情,比如具體壓縮了哪些文件。

如果你不想知道具體壓縮過程,可以添加 -q 選項。

我們將這兩個選項組合起來,最終壓縮命令就是:

zip -rq 壓縮后文件.zip 壓縮前文件

你以為這就結束了?

假設壓縮前的文件命名帶有空格,你直接用上面的命令,那么會出現意想不到的結果,所以為了應對這種情況,我們需要稍作修改,給文件名加個引號(單引號雙引號都可以)括起來。

zip -rq '壓縮后文件.zip' '壓縮前文件'

Step 3: 羅列當前目錄的所有文件

我們知道,羅列當前目錄所有文件只需要使用 ls 命令即可。

所以我們將這個命令返回的結果集用一個變量保存起來,然后我們打印看下效果。

我們修改我們的腳本文件,修改后如下:

FILES=`ls`
echo $FILES

注意這里不是單引號,這里的符號位置在鍵盤左上角處。

然后我們運行腳本:

./batch_zip.sh

就可以看到羅列出的文件了。

Step 4: 循環遍歷所有文件

因為我們的文件都放在集合里面,因此我們需要逐個遍歷獲取,然后逐個進行壓縮操作。

這里用到了循環語句,基本結構如下:

for element in array
do
// TODO
done

// TODO 里面就是你具體要處理的事情。

所以我們可以修改腳本文件如下:

FILES=`ls`
for file in $FILES
do
echo $file
done

這樣運行之后就會逐個打印羅列后的文件名。

如果你當前目錄有文件的名字是包含空格的話,你會發現打印出來的有空格文件名被隔開了。

比如你的文件名是 test 2.txt,則打印會打印出兩行,分別是 test2.txt

因為 ls 命令列出的不同文件就是用空格隔開的。

所以一般情況下推薦命名不要有空格,如果需要分隔,可以用下划線 _。

但是假設真的有怎么辦?

別慌,問題不大。

直接 show 代碼如下:

#!/bin/bash
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")

for file in *
do
  echo $file
done

IFS=$SAVEIFS

具體腳本分析我們就不展開了。大家感興趣可以看文末參考鏈接。

Step 5: 只壓縮目錄

其實我們壓縮的是對於包含大量瑣碎文件的目錄,因此只需要壓縮目錄就可以了。

另外我們的腳本文件因為是文件,包括壓縮文件也是普通文件,因此不需要額外進行排除。

改造后代碼如下:

#!/bin/bash
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")

for file in *
do
  if [ -d $file ]
  then
    echo $file
  fi
done

IFS=$SAVEIFS

修改點在 do-done 塊里面。

主要是增加了一個判斷,當文件是目錄時,才執行打印操作。

Step 6: 替換打印為壓縮命令

結合 Step2 我們最終的腳本命令為:

#!/bin/bash
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")

for file in *
do
  if [ -d $file ]
  then
    zip -rq $file.zip $file
    echo $file was successfully compressed.
  fi
done

IFS=$SAVEIFS

壓縮成功每個文件都會打印一句壓縮成功。

使用

只需要將腳本命令拷貝到你需要壓縮的目錄下面,就可以對跟腳本文件同級的所有目錄進行壓縮。

記得腳本文件需要有可執行權限才能運行。

如果提示沒有權限,可以先運行如下命令添加權限。

chmod u+x batch_zip.sh

下載

大家可以到 GitHub 倉庫上面去直接下載本文最終生成的腳本文件。

https://github.com/nesger/EffectiveTools/blob/master/shell/batch_zip.sh

里面的 README.md 也有具體的用法說明。

優化點

這個腳本命令還有很多地方可以優化,有待大家去完善。

這里列舉如下;

  1. 支持壓縮指定目錄而不是固定為當前目錄,指定目錄通過執行腳本時參數帶入
  2. 壓縮結束后告知本次成功壓縮的總數目
  3. 增加一個邏輯判斷,壓縮成功后是否刪除原文件?可以通過執行腳本時參數帶入

這里就不再描述了,相信對於讀者來說,要實現這些優化也是很簡單的事情。

溫馨提示

其實如果你是要換機器,而且當前系統沒有 bug 的話。

推薦使用時間機器(Time Machine)進行系統遷移。

它相當於把你一台機器上的整個系統(包括文件)進行一個遷移,省去了你重新安裝應用程序和搭建環境的時間。

參考鏈接:
https://www.cyberciti.biz/tips/handling-filenames-with-spaces-in-bash.html
https://www.cnblogs.com/cocowool/archive/2013/01/15/2861904.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM