使用 shell 腳本自動對比兩個安裝目錄並生成差異補丁包

問題的提出

公司各個業務線的安裝包小則幾十兆、大則幾百兆,使用自建的升級系統向全國百萬級用戶下發新版本時,流量耗費相當驚人。有時新版本僅僅改了幾個 dll ,總變更量不過幾十 K 而已,也要發佈一個完整版本。為了降低流量費用,我們推出了補丁升級的方式:產品組將修改的 dll 單獨挑選出來,加上一個配置文件壓縮成包,上傳到自建的升級後台;在客戶端,識別到補丁包類型後,手動解壓並替換各個 dll 完成安裝(之前是直接啟動下載好的安裝包)。這種方式一經推出,受到了業務線的追捧。然而在使用過程中,也發現一些問題,就是在修改完一個源文件後,受影響的往往不止一個 dll,如果僅把其中一兩個 dll 替換了,沒替換的 dll 很可能就會和新的 dll 產生接口不兼容,從而引發崩潰。而有的安裝包包含了幾十個、上百個 dll,如果一一對比,非常費時費力。特別是一些 dll 僅僅是編譯時間不一樣,通過普通的文件對比工具,根本無法判斷這個 dll  的源碼有沒有改過,這讓開發人員非常頭大。

問題的解決

其實這個問題用 c++ 寫個程序是可以解決的,但是一想到要遍歷目錄、構造文件名 map、對比兩個目錄中的文件名、對比相同文件名的內容、複製文件到目標目錄、壓縮目標目錄…這一系列操作時,我覺得還是算了 —— 都得從頭開始寫,工作量不小。而 msys2 或 windows 中就有不少現成的命令可以用,例如對比目錄可以用 diff -r 命令、對比 win32 可執行文件可以用 dumpbin /disasm 命令反編譯然後再用 diff 命令對比、壓縮文件夾可以使用 7z 命令等等,完全不用重複造輪子,直接用 shell 將它們粘合起來就完事了!下面就來看看我是怎麼用 shell 腳本來寫這個小工具吧。

處理命令行參數

這個腳本一開始先處理輸入的命令行參數:

  1 # return code:
  2 # 0 : success
  3 # 1 : no difference
  4 # 2 : compress failure
  5 # 3 : create file/dir failure (privilege ?)
  6 # 126 : file/dir existent
  7 # 127 : invalid arguments
  8 
  9 function usage ()
 10 {
 11     echo "Usage: diffpacker.sh -o oldversionfolder -n newversionfolder -r relativepath -x exportfolder -v version [-s sp] [-t (verbose)] [-e (exactmode)]"
 12     
 13     exit 127
 14 }
 15 
 16 srcdir=
 17 dstdir=
 18 reldir=
 19 outdir=
 20 version=
 21 sp=0
 22 verbose=0
 23 exactmode=0
 24 setupdir="setup"
 25 # pure windows utilities subdir
 26 win32="win32" 
 27 
 28 if [ "${$*/-t//}" != "$*" ]; then
 29     # dump parameters when verbose on
 30     echo "total $# param(s):"
 31     for var in $*; do
 32         echo "$var"
 33     done
 34 fi
 35 
 36 
 37 while getopts "o:n:r:x:v:s:te" arg 
 38 do
 39     case $arg in
 40         o)
 41             srcdir=$OPTARG
 42             ;;
 43         n)
 44             dstdir=$OPTARG
 45             ;;
 46         r)
 47             reldir=$OPTARG
 48             ;;
 49         x)
 50             outdir=$OPTARG
 51             ;;
 52         v)
 53             version=$OPTARG
 54             ;;
 55         s)
 56             sp=$OPTARG
 57             ;;
 58         t)
 59             verbose=1
 60             ;;
 61         e) 
 62             exactmode=1
 63             ;;
 64         ?)  
 65             echo "unkonw argument: $arg"
 66             usage
 67             exit 127
 68             ;;
 69     esac
 70 done
 71 
 72 # reldir can be empty
 73 if [ -z "$srcdir" -o -z "$dstdir" -o -z "$outdir" -o -z "$version" ]; then
 74     echo "empty parameter found: $srcdir, $dstdir, $outdir, $version"
 75     usage
 76     exit 127
 77 fi
 78 
 79 #replace all \ to / to avoid shell string choked on \ 
 80 srcdir=${srcdir//\\/\/}
 81 dstdir=${dstdir//\\/\/}
 82 reldir=${reldir//\\/\/}
 83 outdir=${outdir//\\/\/}
 84 
 85 echo "srcdir=$srcdir"
 86 echo "dstdir=$dstdir"
 87 echo "reldir=$reldir"
 88 echo "outdir=$outdir"
 89 echo "version=$version"
 90 echo "sp=$sp"
 91 echo "verbose=$verbose"
 92 echo "exactmode=$exactmode"
 93 echo ""
 94 
 95 if [ ! -d "$srcdir" ]; then 
 96     echo "not a directory : $srcdir"
 97     exit 126
 98 fi
 99 
100 if [ ! -d "$dstdir" ]; then 
101     echo "not a directory : $dstdir"
102     exit 126
103 fi
104 
105 #if [ -e "$outdir" ]; then
106 resp=$(ls -A "$outdir")
107 if [ "$resp" != "" ]; then
108     echo "out directory not empty: $outdir, fatal error!"
109     exit 126
110 fi 
111 
112 if [ "${outdir:$((${#outdir}-1))}" == "/" ]; then 
113     # remove tailing /
114     outdir=${outdir%?}
115 fi
116 
117 if [ ! -z "$reldir" ] && [ "${reldir:$((${#reldir}-1))}" == "/" ]; then 
118     # remove tailing /
119     reldir=${reldir%?}
120 fi
121 
122 srcasm="src.asm"
123 dstasm="dst.asm"
124 dirdiff="dir.diff"
125 patdiff="diffpattern.txt"
126 itemcnt=0
127 jsonhead=\
128 "{\n"\
129 "  \"version\": \"$version\",\n"\
130 "  \"sp\": \"$sp\",\n"\
131 "  \"actions\": \n"\
132 "  [\n"
133 
134 json=
135 jsontail=\
136 "\n  ]\n"\
137 "}\n"
138 
139 echo "exclude patterns: "
140 while read line
141 do
142     echo $line
143 done < "$patdiff"
144 
145 # to avoid user not end file with \n
146 if [ ! -z "$line" ]; then 
147     echo "$line"
148 fi 
149 echo ""

簡單解說一下:

  • 16-26:聲明用到的變量;
  • 28-34:如果命令行中含有 -t (verbose) 選項,則打印命令行各個參數;
  • 37-70:使用 getopts 命令解析命令行,這個腳本接收以下選項:
    • -o (old) 用於對比的舊目錄;
    • -n (new) 用於對比的新目錄;
    • -r (relative) 補丁包根目錄相對於安裝目錄的位置,有時可能只針對安裝目錄的某個子目錄進行 patch;
    • -x (output) 輸出補丁包的目錄;
    • -v (version) 補丁包版本號,寫入配置文件用;
    • -s (serial pack) 補丁號,寫入配置文件用;
    • -t (verbose) 詳細輸出;
    • -e (exact mode) 配置文件中增加和替換文件項將按每項對應一段 json 的方式精確設置,否則按整個目錄遞歸覆蓋設置。
  • 72-77:空路徑校驗;
  • 79-83:替換路徑中的反斜杠為斜杠,因 shell 會將反斜杠識別為轉義字符的開始;
  • 85-93:打印識別後的各選項,方便出問題時排錯;
  • 95-120:路徑校驗,包括:
    • 對比目錄不得為普通文件;
    • 輸出目錄不得含有文件(防止將中間對比結果和上一次或其它對比結果放在一起打包);
    • 剔除輸出目錄與相對目錄的結尾斜杠(方便後續處理)。
  • 122-137:中間變量的定義,包含反編譯中間文件、目錄對比中間文件、忽略文件模式的中間文件以及生成配置文件的 json 頭和尾;
  • 139-149:在對比目錄時,用戶可以提供一個要忽略的文件模式(pattern)列表,例如不對比 [Dd]ebug、[Ss]ymbol、*.pdb 這些編譯中間目錄或文件,可以使用正則表達式,每行一個。這裡打印這些 pattern 用於排錯。

對比目錄

經過前期的鋪墊,進入第一個重頭戲:

 1 if [ -f "$patdiff" ]; then
 2     diff -qr "$srcdir" "$dstdir" -X "$patdiff" > "$dirdiff"
 3 else
 4     diff -qr "$srcdir" "$dstdir" > "$dirdiff"
 5 fi 
 6 
 7 while read line
 8 do
 9     if [ $verbose != 0 ]; then 
10         echo $line
11     fi 
12 
13     tmp=$(echo $line | sed -n 's/Files \(.*\) and \(.*\) differ$/\1\\n\2/p')
14     if [ ! -z "$tmp" ]; then 
15         left=$(echo -e $tmp | sed -n 1p)
16         right=$(echo -e $tmp | sed -n 2p)
17         if [ $verbose != 0 ]; then 
18             echo -e "left =$left, \nright=$right"
19         fi 
20         ……
21     else 
22         tmp=$(echo $line | sed -n 's/Only in \(.*\): \(.*\)/\1\\n\2/p')
23         if [ ! -z "$tmp" ]; then 
24             isdir=0
25             dir=$(echo -e $tmp | sed -n 1p)
26             file=$(echo -e $tmp | sed -n 2p)
27             if [ -d "$dir/$file" ]; then 
28                 isdir=1
29             fi 
30 
31             if [ $verbose != 0 ]; then 
32                 echo "dir=$dir, file=$file, isdir=$isdir"
33             fi
34             ……
35         else 
36             echo "unrecognized diff output: $line"
37         fi 
38     fi
39     echo ""
40 done < "$dirdiff"

 

這段代碼省略了一些與對比目錄無關的內容,便於看清整個大的流程:

  • 1-5:根據是否有忽略模式文件來調用 diff,當存在這種文件時(上文中的 139-149),增加 -X 選項來添加忽略模式文件到對比目錄過程(diff);否則使用簡單輸出模式(-q)遞歸(-r)對比目錄及其子目錄,輸出內容保存在 dir.diff 文件中;
  • 7,8,40:遍歷 dir.diff 文件內容,根據輸出格式的不同,細分為以下幾類場景:
    • 兩側都有但文件內容不一致:「Files C:/compare/BIMMAKE.old/BmIGMS/TypeRule4Bimface.json and C:/compare/BIMMAKE/BmIGMS/TypeRule4Bimface.json differ」,通過 sed 匹配例子中高亮部分關鍵字,就可以分別提取出舊文件與新文件的完整路徑(分別為 sed 輸出的第一二行,line 13-16);
    • 僅有舊目錄有的內容:「Only in C:/compare/BIMMAKE.old/sdk: ViewerConfig.ini」;
    • 僅有新目錄有的內容:「Only in C:/compare/BIMMAKE/sdk: Mesh.dll」, 以上兩種場景相似,通過 sed 匹配例子中高亮部分關鍵字,就可以分別提取出目錄與文件了(line 22-26),至於是新目錄還是舊目錄,與新舊根目錄做個對比就曉得了,這個後面再說;
    • 兩邊文件一致:不會有任何輸出(這裡必需為 diff 命令使用 -q 選項,不然會將文件內容差異也展示出來,那就非常亂了)。下面是一段完整的對比輸出(內容超長、展開慎重):
      Files C:/compare/BIMMAKE.old/AppBimmake.exe and C:/compare/BIMMAKE/AppBimmake.exe differ
      Files C:/compare/BIMMAKE.old/AppBimmakeImpl.dll and C:/compare/BIMMAKE/AppBimmakeImpl.dll differ
      Files C:/compare/BIMMAKE.old/AppComponentEditor.exe and C:/compare/BIMMAKE/AppComponentEditor.exe differ
      Files C:/compare/BIMMAKE.old/AppComponentEditorImpl.dll and C:/compare/BIMMAKE/AppComponentEditorImpl.dll differ
      Only in C:/compare/BIMMAKE: AppSocketPortConfig.exe
      Only in C:/compare/BIMMAKE: AppSocketPortConfigImpl.dll
      Files C:/compare/BIMMAKE.old/BIMMAKE/Templates/bmDefaultTemplate.gbp and C:/compare/BIMMAKE/BIMMAKE/Templates/bmDefaultTemplate.gbp differ
      Files C:/compare/BIMMAKE.old/BmAnimation.dll and C:/compare/BIMMAKE/BmAnimation.dll differ
      Files C:/compare/BIMMAKE.old/BmAnimationScript.dll and C:/compare/BIMMAKE/BmAnimationScript.dll differ
      Only in C:/compare/BIMMAKE: BmAppSetting.xml
      Files C:/compare/BIMMAKE.old/BmCommonDraw.dll and C:/compare/BIMMAKE/BmCommonDraw.dll differ
      Files C:/compare/BIMMAKE.old/BmCommonEdit.dll and C:/compare/BIMMAKE/BmCommonEdit.dll differ
      Files C:/compare/BIMMAKE.old/BmDataExchange.dll and C:/compare/BIMMAKE/BmDataExchange.dll differ
      Files C:/compare/BIMMAKE.old/BmDrawingExport.dll and C:/compare/BIMMAKE/BmDrawingExport.dll differ
      Files C:/compare/BIMMAKE.old/BmFalcon.dll and C:/compare/BIMMAKE/BmFalcon.dll differ
      Files C:/compare/BIMMAKE.old/BmFamilyBridge.dll and C:/compare/BIMMAKE/BmFamilyBridge.dll differ
      Files C:/compare/BIMMAKE.old/BmGbmpModel.dll and C:/compare/BIMMAKE/BmGbmpModel.dll differ
      Files C:/compare/BIMMAKE.old/BmGbmpUiPlatform.dll and C:/compare/BIMMAKE/BmGbmpUiPlatform.dll differ
      Files C:/compare/BIMMAKE.old/BmGgpUtility.dll and C:/compare/BIMMAKE/BmGgpUtility.dll differ
      Files C:/compare/BIMMAKE.old/BmGuxActionConfig.json and C:/compare/BIMMAKE/BmGuxActionConfig.json differ
      Files C:/compare/BIMMAKE.old/BmHotKeyConfig.xml and C:/compare/BIMMAKE/BmHotKeyConfig.xml differ
      Files C:/compare/BIMMAKE.old/BmIGMS/TypeRule.json and C:/compare/BIMMAKE/BmIGMS/TypeRule.json differ
      Files C:/compare/BIMMAKE.old/BmIGMS/TypeRule4Bimface.json and C:/compare/BIMMAKE/BmIGMS/TypeRule4Bimface.json differ
      Files C:/compare/BIMMAKE.old/BmIGMSExport.dll and C:/compare/BIMMAKE/BmIGMSExport.dll differ
      Files C:/compare/BIMMAKE.old/BmImportGfc.dll and C:/compare/BIMMAKE/BmImportGfc.dll differ
      Files C:/compare/BIMMAKE.old/BmImportIfc.dll and C:/compare/BIMMAKE/BmImportIfc.dll differ
      Files C:/compare/BIMMAKE.old/BmInterOpRevitProject.dll and C:/compare/BIMMAKE/BmInterOpRevitProject.dll differ
      Files C:/compare/BIMMAKE.old/BmInteraction.dll and C:/compare/BIMMAKE/BmInteraction.dll differ
      Files C:/compare/BIMMAKE.old/BmLicense.dll and C:/compare/BIMMAKE/BmLicense.dll differ
      Files C:/compare/BIMMAKE.old/BmModel.dll and C:/compare/BIMMAKE/BmModel.dll differ
      Files C:/compare/BIMMAKE.old/BmMultiThreadNetwork.dll and C:/compare/BIMMAKE/BmMultiThreadNetwork.dll differ
      Files C:/compare/BIMMAKE.old/BmPositioningElements.dll and C:/compare/BIMMAKE/BmPositioningElements.dll differ
      Files C:/compare/BIMMAKE.old/BmRebar.dll and C:/compare/BIMMAKE/BmRebar.dll differ
      Only in C:/compare/BIMMAKE.old: BmRecentDocumentPathRecord.xml
      Files C:/compare/BIMMAKE.old/BmSiteLayout.dll and C:/compare/BIMMAKE/BmSiteLayout.dll differ
      Files C:/compare/BIMMAKE.old/BmSiteLayoutFamily.dll and C:/compare/BIMMAKE/BmSiteLayoutFamily.dll differ
      Files C:/compare/BIMMAKE.old/BmSiteLayoutUi.dll and C:/compare/BIMMAKE/BmSiteLayoutUi.dll differ
      Files C:/compare/BIMMAKE.old/BmStructure.dll and C:/compare/BIMMAKE/BmStructure.dll differ
      Files C:/compare/BIMMAKE.old/BmStructureFamily.dll and C:/compare/BIMMAKE/BmStructureFamily.dll differ
      Files C:/compare/BIMMAKE.old/BmSurfaceSystem.dll and C:/compare/BIMMAKE/BmSurfaceSystem.dll differ
      Files C:/compare/BIMMAKE.old/BmTeighaUtility.dll and C:/compare/BIMMAKE/BmTeighaUtility.dll differ
      Files C:/compare/BIMMAKE.old/BmTest.dll and C:/compare/BIMMAKE/BmTest.dll differ
      Files C:/compare/BIMMAKE.old/BmThirdPartyUpdate.dll and C:/compare/BIMMAKE/BmThirdPartyUpdate.dll differ
      Files C:/compare/BIMMAKE.old/BmUiAnimation.dll and C:/compare/BIMMAKE/BmUiAnimation.dll differ
      Files C:/compare/BIMMAKE.old/BmUiAnimationWidget.dll and C:/compare/BIMMAKE/BmUiAnimationWidget.dll differ
      Files C:/compare/BIMMAKE.old/BmUiCommonComponent.dll and C:/compare/BIMMAKE/BmUiCommonComponent.dll differ
      Files C:/compare/BIMMAKE.old/BmUiDataExchange.dll and C:/compare/BIMMAKE/BmUiDataExchange.dll differ
      Files C:/compare/BIMMAKE.old/BmUiInplaceEdit.dll and C:/compare/BIMMAKE/BmUiInplaceEdit.dll differ
      Files C:/compare/BIMMAKE.old/BmUiPlatform.dll and C:/compare/BIMMAKE/BmUiPlatform.dll differ
      Files C:/compare/BIMMAKE.old/BmUiReBar.dll and C:/compare/BIMMAKE/BmUiReBar.dll differ
      Files C:/compare/BIMMAKE.old/BmUiStructure.dll and C:/compare/BIMMAKE/BmUiStructure.dll differ
      Files C:/compare/BIMMAKE.old/BmUiVisual.dll and C:/compare/BIMMAKE/BmUiVisual.dll differ
      Files C:/compare/BIMMAKE.old/BmVisualModel.dll and C:/compare/BIMMAKE/BmVisualModel.dll differ
      Files C:/compare/BIMMAKE.old/BmWelcomeTemplateFile/MjTemplateFile.xml and C:/compare/BIMMAKE/BmWelcomeTemplateFile/MjTemplateFile.xml differ
      Files C:/compare/BIMMAKE.old/BmWelcomeTemplateFile/二次結構砌體.gbp and C:/compare/BIMMAKE/BmWelcomeTemplateFile/二次結構砌體.gbp differ
      Files C:/compare/BIMMAKE.old/BmWelcomeTemplateFile/二次結構砌體.png and C:/compare/BIMMAKE/BmWelcomeTemplateFile/二次結構砌體.png differ
      Only in C:/compare/BIMMAKE.old/BmWelcomeTemplateFile: 小別墅.gbp
      Only in C:/compare/BIMMAKE.old/BmWelcomeTemplateFile: 小別墅.png
      Files C:/compare/BIMMAKE.old/BmWelcomeTemplateFile/施工場地布置.gbp and C:/compare/BIMMAKE/BmWelcomeTemplateFile/施工場地布置.gbp differ
      Files C:/compare/BIMMAKE.old/BmWelcomeTemplateFile/施工場地布置.png and C:/compare/BIMMAKE/BmWelcomeTemplateFile/施工場地布置.png differ
      Only in C:/compare/BIMMAKE/BmWelcomeTemplateFile: 木模板配模.gbp
      Only in C:/compare/BIMMAKE/BmWelcomeTemplateFile: 木模板配模.png
      Only in C:/compare/BIMMAKE.old/BmWelcomeTemplateFile: 老虎窗屋頂.gbp
      Only in C:/compare/BIMMAKE.old/BmWelcomeTemplateFile: 老虎窗屋頂.png
      Only in C:/compare/BIMMAKE/BmWelcomeTemplateFile: 鋼筋節點深化.gbp
      Only in C:/compare/BIMMAKE/BmWelcomeTemplateFile: 鋼筋節點深化.png
      Files C:/compare/BIMMAKE.old/CadIdentifier/ArchiAlgo.dll and C:/compare/BIMMAKE/CadIdentifier/ArchiAlgo.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/BarInfo.GDB and C:/compare/BIMMAKE/CadIdentifier/BarInfo.GDB differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/BarInfo.GDB.back and C:/compare/BIMMAKE/CadIdentifier/BarInfo.GDB.back differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/CadIdentifier2018.exe and C:/compare/BIMMAKE/CadIdentifier/CadIdentifier2018.exe differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/CmdCore.dll and C:/compare/BIMMAKE/CadIdentifier/CmdCore.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/Common.dll and C:/compare/BIMMAKE/CadIdentifier/Common.dll differ
      Only in C:/compare/BIMMAKE.old/CadIdentifier: DBErrorReport.txt
      Files C:/compare/BIMMAKE.old/CadIdentifier/DBOperations.dll and C:/compare/BIMMAKE/CadIdentifier/DBOperations.dll differ
      Only in C:/compare/BIMMAKE/CadIdentifier: Fonts
      Files C:/compare/BIMMAKE.old/CadIdentifier/GCADIdentification.dll and C:/compare/BIMMAKE/CadIdentifier/GCADIdentification.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GCADModel.dll and C:/compare/BIMMAKE/CadIdentifier/GCADModel.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GCLDataService.dll and C:/compare/BIMMAKE/CadIdentifier/GCLDataService.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GCLProjectDataHelper.dll and C:/compare/BIMMAKE/CadIdentifier/GCLProjectDataHelper.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GCPPMProjDataHelper.dll and C:/compare/BIMMAKE/CadIdentifier/GCPPMProjDataHelper.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GEPEngine.dll and C:/compare/BIMMAKE/CadIdentifier/GEPEngine.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GFCCommon.dll and C:/compare/BIMMAKE/CadIdentifier/GFCCommon.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GGDB.dll and C:/compare/BIMMAKE/CadIdentifier/GGDB.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GGDBDataAwareCtrl.dll and C:/compare/BIMMAKE/CadIdentifier/GGDBDataAwareCtrl.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GGJProjectDataHelper.dll and C:/compare/BIMMAKE/CadIdentifier/GGJProjectDataHelper.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GGJSectionBarEditor.dll and C:/compare/BIMMAKE/CadIdentifier/GGJSectionBarEditor.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GGPViewerProxy.dll and C:/compare/BIMMAKE/CadIdentifier/GGPViewerProxy.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GLDCommon.dll and C:/compare/BIMMAKE/CadIdentifier/GLDCommon.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GLDCrypt.dll and C:/compare/BIMMAKE/CadIdentifier/GLDCrypt.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GLDPrivateCalledPlatform.dll and C:/compare/BIMMAKE/CadIdentifier/GLDPrivateCalledPlatform.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GLDStyles.dll and C:/compare/BIMMAKE/CadIdentifier/GLDStyles.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GLDTableView.dll and C:/compare/BIMMAKE/CadIdentifier/GLDTableView.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GLDThemeEngine.dll and C:/compare/BIMMAKE/CadIdentifier/GLDThemeEngine.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GLDWidget.dll and C:/compare/BIMMAKE/CadIdentifier/GLDWidget.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GLDXML.dll and C:/compare/BIMMAKE/CadIdentifier/GLDXML.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GLDZip.dll and C:/compare/BIMMAKE/CadIdentifier/GLDZip.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GMCommon.dll and C:/compare/BIMMAKE/CadIdentifier/GMCommon.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GMJ.dll and C:/compare/BIMMAKE/CadIdentifier/GMJ.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GMModel.dll and C:/compare/BIMMAKE/CadIdentifier/GMModel.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GMPControls.dll and C:/compare/BIMMAKE/CadIdentifier/GMPControls.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GMPCore.dll and C:/compare/BIMMAKE/CadIdentifier/GMPCore.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GMPRibbonStyle.dll and C:/compare/BIMMAKE/CadIdentifier/GMPRibbonStyle.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GMPUIExtends.dll and C:/compare/BIMMAKE/CadIdentifier/GMPUIExtends.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GMath.dll and C:/compare/BIMMAKE/CadIdentifier/GMath.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GP.dll and C:/compare/BIMMAKE/CadIdentifier/GP.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GRPCommon.dll and C:/compare/BIMMAKE/CadIdentifier/GRPCommon.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GRPEngine.dll and C:/compare/BIMMAKE/CadIdentifier/GRPEngine.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GSP.dll and C:/compare/BIMMAKE/CadIdentifier/GSP.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GSPEngine.dll and C:/compare/BIMMAKE/CadIdentifier/GSPEngine.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GTCADImporter.dll and C:/compare/BIMMAKE/CadIdentifier/GTCADImporter.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GTJBodyBuilder.dll and C:/compare/BIMMAKE/CadIdentifier/GTJBodyBuilder.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GTJCADBeamIdentifier.dll and C:/compare/BIMMAKE/CadIdentifier/GTJCADBeamIdentifier.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GTJCADCmdState.dll and C:/compare/BIMMAKE/CadIdentifier/GTJCADCmdState.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GTJCADColumnDetailIdentifier.dll and C:/compare/BIMMAKE/CadIdentifier/GTJCADColumnDetailIdentifier.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GTJCADCommonAlgorithm.dll and C:/compare/BIMMAKE/CadIdentifier/GTJCADCommonAlgorithm.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GTJCADIdentifier.dll and C:/compare/BIMMAKE/CadIdentifier/GTJCADIdentifier.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GTJCADPlugin.dll and C:/compare/BIMMAKE/CadIdentifier/GTJCADPlugin.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GTJCalcDomainModel.dll and C:/compare/BIMMAKE/CadIdentifier/GTJCalcDomainModel.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GTJCalcExtension.dll and C:/compare/BIMMAKE/CadIdentifier/GTJCalcExtension.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GTJDomainModel.dll and C:/compare/BIMMAKE/CadIdentifier/GTJDomainModel.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GTJGeneralAlgorithm.dll and C:/compare/BIMMAKE/CadIdentifier/GTJGeneralAlgorithm.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GTJGeneralUtility.dll and C:/compare/BIMMAKE/CadIdentifier/GTJGeneralUtility.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GTJModelCmdState.dll and C:/compare/BIMMAKE/CadIdentifier/GTJModelCmdState.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GTJModelDAO.dll and C:/compare/BIMMAKE/CadIdentifier/GTJModelDAO.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GTJModelExtension.dll and C:/compare/BIMMAKE/CadIdentifier/GTJModelExtension.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GTJModelPlugin.dll and C:/compare/BIMMAKE/CadIdentifier/GTJModelPlugin.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GTJProjectDataHelper.dll and C:/compare/BIMMAKE/CadIdentifier/GTJProjectDataHelper.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GTJUIModule.dll and C:/compare/BIMMAKE/CadIdentifier/GTJUIModule.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GTTchEntity_4.00_10.tx and C:/compare/BIMMAKE/CadIdentifier/GTTchEntity_4.00_10.tx differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GUC.dll and C:/compare/BIMMAKE/CadIdentifier/GUC.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/Geometry.dll and C:/compare/BIMMAKE/CadIdentifier/Geometry.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/GfcClasses.dll and C:/compare/BIMMAKE/CadIdentifier/GfcClasses.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/Layout and C:/compare/BIMMAKE/CadIdentifier/Layout differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/MDCache.dll and C:/compare/BIMMAKE/CadIdentifier/MDCache.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/MDCmdLog.dll and C:/compare/BIMMAKE/CadIdentifier/MDCmdLog.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/MDCommon.dll and C:/compare/BIMMAKE/CadIdentifier/MDCommon.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/MDScript.dll and C:/compare/BIMMAKE/CadIdentifier/MDScript.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/MaterialCore.dll and C:/compare/BIMMAKE/CadIdentifier/MaterialCore.dll differ
      Only in C:/compare/BIMMAKE/CadIdentifier: Microsoft.DTfW.DHL.manifest
      Files C:/compare/BIMMAKE.old/CadIdentifier/RenderSystemAngle.dll and C:/compare/BIMMAKE/CadIdentifier/RenderSystemAngle.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/RenderSystemGL.dll and C:/compare/BIMMAKE/CadIdentifier/RenderSystemGL.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/Ubc.dll and C:/compare/BIMMAKE/CadIdentifier/Ubc.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/UserInfo.GDB and C:/compare/BIMMAKE/CadIdentifier/UserInfo.GDB differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/UserInfo.GDB.ggdblog.dat and C:/compare/BIMMAKE/CadIdentifier/UserInfo.GDB.ggdblog.dat differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/VDECore.dll and C:/compare/BIMMAKE/CadIdentifier/VDECore.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/VectorDrawing.dll and C:/compare/BIMMAKE/CadIdentifier/VectorDrawing.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/ViewCore.dll and C:/compare/BIMMAKE/CadIdentifier/ViewCore.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/ViewManager.dll and C:/compare/BIMMAKE/CadIdentifier/ViewManager.dll differ
      Only in C:/compare/BIMMAKE/CadIdentifier: filedialog.ini
      Files C:/compare/BIMMAKE.old/CadIdentifier/gsolver.dll and C:/compare/BIMMAKE/CadIdentifier/gsolver.dll differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/skin/CoolDark.rcc and C:/compare/BIMMAKE/CadIdentifier/skin/CoolDark.rcc differ
      Files C:/compare/BIMMAKE.old/CadIdentifier/skin/SilveryWhite.rcc and C:/compare/BIMMAKE/CadIdentifier/skin/SilveryWhite.rcc differ
      Only in C:/compare/BIMMAKE/ComponentEditor/Templates/GFCFamily: 倒稜台獨立基礎.gac
      Only in C:/compare/BIMMAKE/ComponentEditor/Templates/GFCFamily: 偏心二階獨立基礎.gac
      Only in C:/compare/BIMMAKE/ComponentEditor/Templates/GFCFamily: 雙台雙杯口獨立基礎.gac
      Only in C:/compare/BIMMAKE/ComponentEditor/Templates/GFCFamily: 四稜錐台形獨立基礎.gac
      Only in C:/compare/BIMMAKE/ComponentEditor/Templates/GFCFamily: 四稜錐台形獨立基礎帶柱.gac
      Only in C:/compare/BIMMAKE/ComponentEditor/Templates/GFCFamily: 帶短柱杯口獨立基礎.gac
      Only in C:/compare/BIMMAKE/ComponentEditor/Templates/GFCFamily: 底偏心矩形獨立基礎.gac
      Only in C:/compare/BIMMAKE/ComponentEditor/Templates/GFCFamily: 杯形基礎.gac
      Only in C:/compare/BIMMAKE/ComponentEditor/Templates/GFCFamily: 獨立基礎三台.gac
      Only in C:/compare/BIMMAKE/ComponentEditor/Templates/GFCFamily: 獨立基礎三台有杯口.gac
      Only in C:/compare/BIMMAKE/ComponentEditor/Templates/GFCFamily: 獨立基礎雙層帶坡.gac
      Only in C:/compare/BIMMAKE/ComponentEditor/Templates/GFCFamily: 等高磚大放腳獨立基礎.gac
      Only in C:/compare/BIMMAKE/ComponentEditor/Templates/GFCFamily: 錐台杯形獨立基礎.gac
      Only in C:/compare/BIMMAKE/ComponentEditor/Templates/GFCFamily: 頂偏心矩形獨立基礎.gac
      Files C:/compare/BIMMAKE.old/ComponentEditorUiConfiguration.dll and C:/compare/BIMMAKE/ComponentEditorUiConfiguration.dll differ
      Files C:/compare/BIMMAKE.old/ComponentEditorUiPlatform.dll and C:/compare/BIMMAKE/ComponentEditorUiPlatform.dll differ
      Only in C:/compare/BIMMAKE: CopyLibraries.bat
      Files C:/compare/BIMMAKE.old/CopyTemplates.bat and C:/compare/BIMMAKE/CopyTemplates.bat differ
      Only in C:/compare/BIMMAKE: Crx.dll
      Only in C:/compare/BIMMAKE: CrxDb.dll
      Only in C:/compare/BIMMAKE: CrxGe.dll
      Only in C:/compare/BIMMAKE: CrxSpt.dll
      Only in C:/compare/BIMMAKE: DbAnnotate.dll
      Only in C:/compare/BIMMAKE: DbBase.dll
      Only in C:/compare/BIMMAKE: DbBom.dll
      Only in C:/compare/BIMMAKE: DbCurve.dll
      Only in C:/compare/BIMMAKE: DbEntity.dll
      Only in C:/compare/BIMMAKE: DbStandard.dll
      Only in C:/compare/BIMMAKE: DbStyle.dll
      Only in C:/compare/BIMMAKE: DbText.dll
      Only in C:/compare/BIMMAKE: Debug.ini
      Only in C:/compare/BIMMAKE: DeleteLibraries.bat
      Only in C:/compare/BIMMAKE: DftConfig.dll
      Only in C:/compare/BIMMAKE: DftDb.dll
      Files C:/compare/BIMMAKE.old/FamilyCategories.xml and C:/compare/BIMMAKE/FamilyCategories.xml differ
      Files C:/compare/BIMMAKE.old/FamilyDialogLauout.xml and C:/compare/BIMMAKE/FamilyDialogLauout.xml differ
      Only in C:/compare/BIMMAKE: FillPatternFileApiTestData
      Files C:/compare/BIMMAKE.old/GGPMaterialService.dll and C:/compare/BIMMAKE/GGPMaterialService.dll differ
      Files C:/compare/BIMMAKE.old/GGPMaterialUI.dll and C:/compare/BIMMAKE/GGPMaterialUI.dll differ
      Only in C:/compare/BIMMAKE.old: GPUDriverConfig.ini
      Files C:/compare/BIMMAKE.old/GVideoFFmpeg.dll and C:/compare/BIMMAKE/GVideoFFmpeg.dll differ
      Only in C:/compare/BIMMAKE: GbmpModel.dll
      Files C:/compare/BIMMAKE.old/Gcmp3ds.dll and C:/compare/BIMMAKE/Gcmp3ds.dll differ
      Files C:/compare/BIMMAKE.old/GcmpApplication.dll and C:/compare/BIMMAKE/GcmpApplication.dll differ
      Files C:/compare/BIMMAKE.old/GcmpApplicationImpl.dll and C:/compare/BIMMAKE/GcmpApplicationImpl.dll differ
      Files C:/compare/BIMMAKE.old/GcmpApplicationInterface.dll and C:/compare/BIMMAKE/GcmpApplicationInterface.dll differ
      Files C:/compare/BIMMAKE.old/GcmpCommandAction.dll and C:/compare/BIMMAKE/GcmpCommandAction.dll differ
      Files C:/compare/BIMMAKE.old/GcmpCommonDraw.dll and C:/compare/BIMMAKE/GcmpCommonDraw.dll differ
      Files C:/compare/BIMMAKE.old/GcmpCommonEdit.dll and C:/compare/BIMMAKE/GcmpCommonEdit.dll differ
      Files C:/compare/BIMMAKE.old/GcmpDebug.dll and C:/compare/BIMMAKE/GcmpDebug.dll differ
      Only in C:/compare/BIMMAKE: GcmpDrawingEdit.dll
      Only in C:/compare/BIMMAKE: GcmpDrawingText.dll
      Files C:/compare/BIMMAKE.old/GcmpDwgDxf.dll and C:/compare/BIMMAKE/GcmpDwgDxf.dll differ
      Files C:/compare/BIMMAKE.old/GcmpGuiInterface.dll and C:/compare/BIMMAKE/GcmpGuiInterface.dll differ
      Only in C:/compare/BIMMAKE: GcmpGuiMainFrame.dll
      Files C:/compare/BIMMAKE.old/GcmpGuiQt.dll and C:/compare/BIMMAKE/GcmpGuiQt.dll differ
      Files C:/compare/BIMMAKE.old/GcmpIntrinsicGuids.json and C:/compare/BIMMAKE/GcmpIntrinsicGuids.json differ
      Files C:/compare/BIMMAKE.old/GcmpJournal.dll and C:/compare/BIMMAKE/GcmpJournal.dll differ
      Files C:/compare/BIMMAKE.old/GcmpLocatorCommands.dll and C:/compare/BIMMAKE/GcmpLocatorCommands.dll differ
      Files C:/compare/BIMMAKE.old/GcmpSkpGGP.dll and C:/compare/BIMMAKE/GcmpSkpGGP.dll differ
      Files C:/compare/BIMMAKE.old/GcmpSkpInterface.dll and C:/compare/BIMMAKE/GcmpSkpInterface.dll differ
      Only in C:/compare/BIMMAKE: GcmpSocketPortConfigData.dll
      Files C:/compare/BIMMAKE.old/GcmpTestFamily.dll and C:/compare/BIMMAKE/GcmpTestFamily.dll differ
      Files C:/compare/BIMMAKE.old/GcmpThirdPartyUpdate.dll and C:/compare/BIMMAKE/GcmpThirdPartyUpdate.dll differ
      Only in C:/compare/BIMMAKE: GcmpUiCommandAction.dll
      Files C:/compare/BIMMAKE.old/GcmpUiDrawingExportFamily.dll and C:/compare/BIMMAKE/GcmpUiDrawingExportFamily.dll differ
      Files C:/compare/BIMMAKE.old/GcmpUiPlatform.dll and C:/compare/BIMMAKE/GcmpUiPlatform.dll differ
      Files C:/compare/BIMMAKE.old/GcmpUiPlatformFamily.dll and C:/compare/BIMMAKE/GcmpUiPlatformFamily.dll differ
      Only in C:/compare/BIMMAKE: GcmpUiView.dll
      Only in C:/compare/BIMMAKE: GcmpUiViewInterface.dll
      Files C:/compare/BIMMAKE.old/GcmpViewCommands.dll and C:/compare/BIMMAKE/GcmpViewCommands.dll differ
      Files C:/compare/BIMMAKE.old/GmAPITest.dll and C:/compare/BIMMAKE/GmAPITest.dll differ
      Files C:/compare/BIMMAKE.old/GmCloudStorage.dll and C:/compare/BIMMAKE/GmCloudStorage.dll differ
      Files C:/compare/BIMMAKE.old/GmCloudStorageQtImp.dll and C:/compare/BIMMAKE/GmCloudStorageQtImp.dll differ
      Files C:/compare/BIMMAKE.old/GmConstruction.dll and C:/compare/BIMMAKE/GmConstruction.dll differ
      Files C:/compare/BIMMAKE.old/GmDataSynchronization.dll and C:/compare/BIMMAKE/GmDataSynchronization.dll differ
      Files C:/compare/BIMMAKE.old/GmInplaceEdit.dll and C:/compare/BIMMAKE/GmInplaceEdit.dll differ
      Only in C:/compare/BIMMAKE: GmPositioningElements.dll
      Files C:/compare/BIMMAKE.old/GmUiCommonComponent.dll and C:/compare/BIMMAKE/GmUiCommonComponent.dll differ
      Files C:/compare/BIMMAKE.old/GmUiInplaceEditCommon.dll and C:/compare/BIMMAKE/GmUiInplaceEditCommon.dll differ
      Files C:/compare/BIMMAKE.old/GmUiInplaceEditFamily.dll and C:/compare/BIMMAKE/GmUiInplaceEditFamily.dll differ
      Files C:/compare/BIMMAKE.old/GmUiModelFamily.dll and C:/compare/BIMMAKE/GmUiModelFamily.dll differ
      Only in C:/compare/BIMMAKE: GmUiPlatform.dll
      Files C:/compare/BIMMAKE.old/GuxClient.dll and C:/compare/BIMMAKE/GuxClient.dll differ
      Files C:/compare/BIMMAKE.old/HardWareInfo.dll and C:/compare/BIMMAKE/HardWareInfo.dll differ
      Files C:/compare/BIMMAKE.old/InstallGbmpAddin.exe and C:/compare/BIMMAKE/InstallGbmpAddin.exe differ
      Files C:/compare/BIMMAKE.old/InterOpGBMP2014.dll and C:/compare/BIMMAKE/InterOpGBMP2014.dll differ
      Files C:/compare/BIMMAKE.old/InterOpGBMP2015.dll and C:/compare/BIMMAKE/InterOpGBMP2015.dll differ
      Files C:/compare/BIMMAKE.old/InterOpGBMP2016.dll and C:/compare/BIMMAKE/InterOpGBMP2016.dll differ
      Files C:/compare/BIMMAKE.old/InterOpGBMP2017.dll and C:/compare/BIMMAKE/InterOpGBMP2017.dll differ
      Files C:/compare/BIMMAKE.old/InterOpGBMP2018.dll and C:/compare/BIMMAKE/InterOpGBMP2018.dll differ
      Files C:/compare/BIMMAKE.old/InterOpGBMP2019.dll and C:/compare/BIMMAKE/InterOpGBMP2019.dll differ
      Files C:/compare/BIMMAKE.old/InterOpGBMP2020.dll and C:/compare/BIMMAKE/InterOpGBMP2020.dll differ
      Files C:/compare/BIMMAKE.old/InterOpGBMPHelper.exe and C:/compare/BIMMAKE/InterOpGBMPHelper.exe differ
      Files C:/compare/BIMMAKE.old/InterOpRevitConfig.xml and C:/compare/BIMMAKE/InterOpRevitConfig.xml differ
      Files C:/compare/BIMMAKE.old/InterOpRevitFamily.dll and C:/compare/BIMMAKE/InterOpRevitFamily.dll differ
      Files C:/compare/BIMMAKE.old/KillProcess.bat and C:/compare/BIMMAKE/KillProcess.bat differ
      Only in C:/compare/BIMMAKE: KnlAPIBase.dll
      Only in C:/compare/BIMMAKE: KnlModuleManager.dll
      Only in C:/compare/BIMMAKE: KnlProfile.dll
      Only in C:/compare/BIMMAKE: KnlXmlParser.dll
      Only in C:/compare/BIMMAKE: Libraries
      Only in C:/compare/BIMMAKE: MDLMechanical.dll
      Files C:/compare/BIMMAKE.old/MaterialLibraryApplication.dll and C:/compare/BIMMAKE/MaterialLibraryApplication.dll differ
      Files C:/compare/BIMMAKE.old/MaterialUI.dll and C:/compare/BIMMAKE/MaterialUI.dll differ
      Files C:/compare/BIMMAKE.old/MjArithmetic.dll and C:/compare/BIMMAKE/MjArithmetic.dll differ
      Files C:/compare/BIMMAKE.old/MjCaculateModel.dll and C:/compare/BIMMAKE/MjCaculateModel.dll differ
      Files C:/compare/BIMMAKE.old/MjCommon.dll and C:/compare/BIMMAKE/MjCommon.dll differ
      Files C:/compare/BIMMAKE.old/MjDeliverables.dll and C:/compare/BIMMAKE/MjDeliverables.dll differ
      Files C:/compare/BIMMAKE.old/MjGeometryGGP.dll and C:/compare/BIMMAKE/MjGeometryGGP.dll differ
      Only in C:/compare/BIMMAKE.old: MjLicense.dll
      Files C:/compare/BIMMAKE.old/MjOperationScaffoldModel.dll and C:/compare/BIMMAKE/MjOperationScaffoldModel.dll differ
      Files C:/compare/BIMMAKE.old/MjPracticeModel.dll and C:/compare/BIMMAKE/MjPracticeModel.dll differ
      Files C:/compare/BIMMAKE.old/MjQtGuiImplementation.dll and C:/compare/BIMMAKE/MjQtGuiImplementation.dll differ
      Only in C:/compare/BIMMAKE.old: MjRichTextEditor.dll
      Files C:/compare/BIMMAKE.old/MjScaffoldModel.dll and C:/compare/BIMMAKE/MjScaffoldModel.dll differ
      Files C:/compare/BIMMAKE.old/MjShoringScaffoldModel.dll and C:/compare/BIMMAKE/MjShoringScaffoldModel.dll differ
      Files C:/compare/BIMMAKE.old/MjStructureComponent.dll and C:/compare/BIMMAKE/MjStructureComponent.dll differ
      Only in C:/compare/BIMMAKE.old: MjUIArchitecture.dll
      Files C:/compare/BIMMAKE.old/MjUIPlatform.dll and C:/compare/BIMMAKE/MjUIPlatform.dll differ
      Files C:/compare/BIMMAKE.old/MjUIScaffoldArrangement.dll and C:/compare/BIMMAKE/MjUIScaffoldArrangement.dll differ
      Files C:/compare/BIMMAKE.old/MjUITool.dll and C:/compare/BIMMAKE/MjUITool.dll differ
      Only in C:/compare/BIMMAKE.old: Packing4Rendering.dll
      Only in C:/compare/BIMMAKE: Peimo.exe
      Files C:/compare/BIMMAKE.old/QCefView.dll and C:/compare/BIMMAKE/QCefView.dll differ
      Only in C:/compare/BIMMAKE.old: QProfile.txt
      Files C:/compare/BIMMAKE.old/QtCommonWidget.dll and C:/compare/BIMMAKE/QtCommonWidget.dll differ
      Only in C:/compare/BIMMAKE.old: RecentDocumentPathRecord.xml
      Files C:/compare/BIMMAKE.old/RecordInstall.bat and C:/compare/BIMMAKE/RecordInstall.bat differ
      Files C:/compare/BIMMAKE.old/RecordUninstall.bat and C:/compare/BIMMAKE/RecordUninstall.bat differ
      Files C:/compare/BIMMAKE.old/RemoveFiles.bat and C:/compare/BIMMAKE/RemoveFiles.bat differ
      Files C:/compare/BIMMAKE.old/Revision.txt and C:/compare/BIMMAKE/Revision.txt differ
      Files C:/compare/BIMMAKE.old/ServiceView.dll and C:/compare/BIMMAKE/ServiceView.dll differ
      Only in C:/compare/BIMMAKE/Share/ViewCoreResources/MaterialLibrary/textures: rainTextures
      Only in C:/compare/BIMMAKE/Share/ViewCoreResources/MaterialLibrary/textures: rainTexturesAmbient
      Only in C:/compare/BIMMAKE/Share/ViewCoreResources/Shaders: DoubleSideShader
      Only in C:/compare/BIMMAKE/Share/ViewCoreResources/Shaders: Particle
      Only in C:/compare/BIMMAKE/Share/ViewCoreResources/Shaders: Rain
      Only in C:/compare/BIMMAKE: SptCx.dll
      Only in C:/compare/BIMMAKE: SptCxGe.dll
      Only in C:/compare/BIMMAKE: SptCxMath.dll
      Only in C:/compare/BIMMAKE: SptGe.dll
      Only in C:/compare/BIMMAKE: SptGi.dll
      Only in C:/compare/BIMMAKE: SptMath.dll
      Only in C:/compare/BIMMAKE: SptNLS.dll
      Only in C:/compare/BIMMAKE: SysFactory.dll
      Files C:/compare/BIMMAKE.old/Teigha/ACCAMERA_20.8src_14.tx and C:/compare/BIMMAKE/Teigha/ACCAMERA_20.8src_14.tx differ
      Files C:/compare/BIMMAKE.old/Teigha/ATEXT_20.8src_14.tx and C:/compare/BIMMAKE/Teigha/ATEXT_20.8src_14.tx differ
      Files C:/compare/BIMMAKE.old/Teigha/AcMPolygonObj15_20.8src_14.tx and C:/compare/BIMMAKE/Teigha/AcMPolygonObj15_20.8src_14.tx differ
      Only in C:/compare/BIMMAKE/Teigha: GripPoints_20.8src_14.tx
      Files C:/compare/BIMMAKE.old/Teigha/ISM_20.8src_14.tx and C:/compare/BIMMAKE/Teigha/ISM_20.8src_14.tx differ
      Files C:/compare/BIMMAKE.old/Teigha/PDFiumModule_20.8src_14.tx and C:/compare/BIMMAKE/Teigha/PDFiumModule_20.8src_14.tx differ
      Files C:/compare/BIMMAKE.old/Teigha/RText_20.8src_14.tx and C:/compare/BIMMAKE/Teigha/RText_20.8src_14.tx differ
      Files C:/compare/BIMMAKE.old/Teigha/RxRasterServices_20.8src_14.tx and C:/compare/BIMMAKE/Teigha/RxRasterServices_20.8src_14.tx differ
      Files C:/compare/BIMMAKE.old/Teigha/SCENEOE_20.8src_14.tx and C:/compare/BIMMAKE/Teigha/SCENEOE_20.8src_14.tx differ
      Files C:/compare/BIMMAKE.old/Teigha/TD_Alloc_20.8src_14.dll and C:/compare/BIMMAKE/Teigha/TD_Alloc_20.8src_14.dll differ
      Only in C:/compare/BIMMAKE/Teigha: TD_Ave_20.8src_14.tx
      Files C:/compare/BIMMAKE.old/Teigha/TD_DbCore_20.8src_14.dll and C:/compare/BIMMAKE/Teigha/TD_DbCore_20.8src_14.dll differ
      Files C:/compare/BIMMAKE.old/Teigha/TD_DbEntities_20.8src_14.tx and C:/compare/BIMMAKE/Teigha/TD_DbEntities_20.8src_14.tx differ
      Files C:/compare/BIMMAKE.old/Teigha/TD_DbIO_20.8src_14.tx and C:/compare/BIMMAKE/Teigha/TD_DbIO_20.8src_14.tx differ
      Files C:/compare/BIMMAKE.old/Teigha/TD_DbRoot_20.8src_14.dll and C:/compare/BIMMAKE/Teigha/TD_DbRoot_20.8src_14.dll differ
      Files C:/compare/BIMMAKE.old/Teigha/TD_Db_20.8src_14.dll and C:/compare/BIMMAKE/Teigha/TD_Db_20.8src_14.dll differ
      Only in C:/compare/BIMMAKE/Teigha: TD_DynBlocks_20.8src_14.tx
      Files C:/compare/BIMMAKE.old/Teigha/TD_Ge_20.8src_14.dll and C:/compare/BIMMAKE/Teigha/TD_Ge_20.8src_14.dll differ
      Files C:/compare/BIMMAKE.old/Teigha/TD_Gi_20.8src_14.dll and C:/compare/BIMMAKE/Teigha/TD_Gi_20.8src_14.dll differ
      Files C:/compare/BIMMAKE.old/Teigha/TD_Gs_20.8src_14.dll and C:/compare/BIMMAKE/Teigha/TD_Gs_20.8src_14.dll differ
      Files C:/compare/BIMMAKE.old/Teigha/TD_PdfImport_20.8src_14.tx and C:/compare/BIMMAKE/Teigha/TD_PdfImport_20.8src_14.tx differ
      Files C:/compare/BIMMAKE.old/Teigha/TD_Pdfium.dll and C:/compare/BIMMAKE/Teigha/TD_Pdfium.dll differ
      Files C:/compare/BIMMAKE.old/Teigha/TD_Root_20.8src_14.dll and C:/compare/BIMMAKE/Teigha/TD_Root_20.8src_14.dll differ
      Files C:/compare/BIMMAKE.old/Teigha/TD_SpatialIndex_20.8src_14.dll and C:/compare/BIMMAKE/Teigha/TD_SpatialIndex_20.8src_14.dll differ
      Files C:/compare/BIMMAKE.old/Teigha/TD_Zlib.dll and C:/compare/BIMMAKE/Teigha/TD_Zlib.dll differ
      Files C:/compare/BIMMAKE.old/Teigha/WipeOut_20.8src_14.tx and C:/compare/BIMMAKE/Teigha/WipeOut_20.8src_14.tx differ
      Files C:/compare/BIMMAKE.old/TeighaUtility.dll and C:/compare/BIMMAKE/TeighaUtility.dll differ
      Files C:/compare/BIMMAKE.old/UE4JsonExporter.dll and C:/compare/BIMMAKE/UE4JsonExporter.dll differ
      Only in C:/compare/BIMMAKE.old: ViewerConfig.ini
      Files C:/compare/BIMMAKE.old/ViewerTileMerger.exe and C:/compare/BIMMAKE/ViewerTileMerger.exe differ
      Only in C:/compare/BIMMAKE.old: algorithmLog.ini
      Files C:/compare/BIMMAKE.old/bimmake_ver.txt and C:/compare/BIMMAKE/bimmake_ver.txt differ
      Files C:/compare/BIMMAKE.old/bm_category_and_style_config/BIMMAKECategories.xml and C:/compare/BIMMAKE/bm_category_and_style_config/BIMMAKECategories.xml differ
      Files C:/compare/BIMMAKE.old/bm_category_and_style_config/SiteLayoutCategories.xml and C:/compare/BIMMAKE/bm_category_and_style_config/SiteLayoutCategories.xml differ
      Only in C:/compare/BIMMAKE/bm_plugin_config/DB: MjOperationScaffoldModel.addin
      Only in C:/compare/BIMMAKE/bm_plugin_config: MjUIPlatform.addin
      Only in C:/compare/BIMMAKE: en-US
      Files C:/compare/BIMMAKE.old/gbmp_gcmp_behavior_config.xml and C:/compare/BIMMAKE/gbmp_gcmp_behavior_config.xml differ
      Only in C:/compare/BIMMAKE/gbmp_plugin_config: GcmpInternalTest.addin
      Only in C:/compare/BIMMAKE/gbmp_plugin_config: GcmpTest.addin
      Only in C:/compare/BIMMAKE.old: gdpcore.1.txt
      Only in C:/compare/BIMMAKE.old: gdpcore.txt
      Files C:/compare/BIMMAKE.old/journal_config.json and C:/compare/BIMMAKE/journal_config.json differ
      Files C:/compare/BIMMAKE.old/qtcefwing.exe and C:/compare/BIMMAKE/qtcefwing.exe differ
      Files C:/compare/BIMMAKE.old/sdk/AppFamilyServiceProvider.exe and C:/compare/BIMMAKE/sdk/AppFamilyServiceProvider.exe differ
      Files C:/compare/BIMMAKE.old/sdk/AppFamilyServiceProviderImpl.dll and C:/compare/BIMMAKE/sdk/AppFamilyServiceProviderImpl.dll differ
      Files C:/compare/BIMMAKE.old/sdk/ArchiAlgo.dll and C:/compare/BIMMAKE/sdk/ArchiAlgo.dll differ
      Files C:/compare/BIMMAKE.old/sdk/BmFamilyCustomData.dll and C:/compare/BIMMAKE/sdk/BmFamilyCustomData.dll differ
      Only in C:/compare/BIMMAKE/sdk: CGBase.dll
      Files C:/compare/BIMMAKE.old/sdk/CategoryAndStyleDataDataBase/GCMPCategories.xml and C:/compare/BIMMAKE/sdk/CategoryAndStyleDataDataBase/GCMPCategories.xml differ
      Files C:/compare/BIMMAKE.old/sdk/CmdCore.dll and C:/compare/BIMMAKE/sdk/CmdCore.dll differ
      Files C:/compare/BIMMAKE.old/sdk/Common.dll and C:/compare/BIMMAKE/sdk/Common.dll differ
      Files C:/compare/BIMMAKE.old/sdk/ExprEngine.dll and C:/compare/BIMMAKE/sdk/ExprEngine.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GMath.dll and C:/compare/BIMMAKE/sdk/GMath.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GSolver.dll and C:/compare/BIMMAKE/sdk/GSolver.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpActionInterface.dll and C:/compare/BIMMAKE/sdk/GcmpActionInterface.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpAddin.dll and C:/compare/BIMMAKE/sdk/GcmpAddin.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpCollaborationInterface.dll and C:/compare/BIMMAKE/sdk/GcmpCollaborationInterface.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpCommandInterface.dll and C:/compare/BIMMAKE/sdk/GcmpCommandInterface.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpDatabase.dll and C:/compare/BIMMAKE/sdk/GcmpDatabase.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpDatabaseInterface.dll and C:/compare/BIMMAKE/sdk/GcmpDatabaseInterface.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpDbCommonEdit.dll and C:/compare/BIMMAKE/sdk/GcmpDbCommonEdit.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpDevService.dll and C:/compare/BIMMAKE/sdk/GcmpDevService.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpDwgDxfInterface.dll and C:/compare/BIMMAKE/sdk/GcmpDwgDxfInterface.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpFoundation.dll and C:/compare/BIMMAKE/sdk/GcmpFoundation.dll differ
      Only in C:/compare/BIMMAKE/sdk: GcmpGUiBaseImpl.dll
      Only in C:/compare/BIMMAKE/sdk: GcmpGUiBaseInterface.dll
      Files C:/compare/BIMMAKE.old/sdk/GcmpGdcModel.dll and C:/compare/BIMMAKE/sdk/GcmpGdcModel.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpGeometryACIS.dll and C:/compare/BIMMAKE/sdk/GcmpGeometryACIS.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpGeometryGGP.dll and C:/compare/BIMMAKE/sdk/GcmpGeometryGGP.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpGeometryInterface.dll and C:/compare/BIMMAKE/sdk/GcmpGeometryInterface.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpGraphicsNode.dll and C:/compare/BIMMAKE/sdk/GcmpGraphicsNode.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpGraphicsNodeInterface.dll and C:/compare/BIMMAKE/sdk/GcmpGraphicsNodeInterface.dll differ
      Only in C:/compare/BIMMAKE/sdk: GcmpGuiMainFrameInterface.dll
      Files C:/compare/BIMMAKE.old/sdk/GcmpGuiResourceQt.dll and C:/compare/BIMMAKE/sdk/GcmpGuiResourceQt.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpJournalInterface.dll and C:/compare/BIMMAKE/sdk/GcmpJournalInterface.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpMathInterface.dll and C:/compare/BIMMAKE/sdk/GcmpMathInterface.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpModel.dll and C:/compare/BIMMAKE/sdk/GcmpModel.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpModelInterface.dll and C:/compare/BIMMAKE/sdk/GcmpModelInterface.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpPick.dll and C:/compare/BIMMAKE/sdk/GcmpPick.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpPickInterface.dll and C:/compare/BIMMAKE/sdk/GcmpPickInterface.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpRenderingGGP.dll and C:/compare/BIMMAKE/sdk/GcmpRenderingGGP.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpRenderingInterface.dll and C:/compare/BIMMAKE/sdk/GcmpRenderingInterface.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpSnap.dll and C:/compare/BIMMAKE/sdk/GcmpSnap.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpSnapInterface.dll and C:/compare/BIMMAKE/sdk/GcmpSnapInterface.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpTypeCastGGP.dll and C:/compare/BIMMAKE/sdk/GcmpTypeCastGGP.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpUiInterface.dll and C:/compare/BIMMAKE/sdk/GcmpUiInterface.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GcmpUiQtImpl.dll and C:/compare/BIMMAKE/sdk/GcmpUiQtImpl.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GdcCommon.dll and C:/compare/BIMMAKE/sdk/GdcCommon.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GdcCore.dll and C:/compare/BIMMAKE/sdk/GdcCore.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GdcDataStandard.dll and C:/compare/BIMMAKE/sdk/GdcDataStandard.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GdcEngine.dll and C:/compare/BIMMAKE/sdk/GdcEngine.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GdcJsonSerializer.dll and C:/compare/BIMMAKE/sdk/GdcJsonSerializer.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GdcLocalDatabase.dll and C:/compare/BIMMAKE/sdk/GdcLocalDatabase.dll differ
      Only in C:/compare/BIMMAKE/sdk: GdcLogging.dll
      Files C:/compare/BIMMAKE.old/sdk/GdcNetwork.dll and C:/compare/BIMMAKE/sdk/GdcNetwork.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GdcProjectManager.dll and C:/compare/BIMMAKE/sdk/GdcProjectManager.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GdcUserManager.dll and C:/compare/BIMMAKE/sdk/GdcUserManager.dll differ
      Files C:/compare/BIMMAKE.old/sdk/Geometry.dll and C:/compare/BIMMAKE/sdk/Geometry.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GmArchitectureFamily.dll and C:/compare/BIMMAKE/sdk/GmArchitectureFamily.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GmCompress.dll and C:/compare/BIMMAKE/sdk/GmCompress.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GmCrossDomainMessager.dll and C:/compare/BIMMAKE/sdk/GmCrossDomainMessager.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GmFamilyCustomData.dll and C:/compare/BIMMAKE/sdk/GmFamilyCustomData.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GmFamilyService.dll and C:/compare/BIMMAKE/sdk/GmFamilyService.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GmFamilyServiceInterface.dll and C:/compare/BIMMAKE/sdk/GmFamilyServiceInterface.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GmFamilyUpdate.dll and C:/compare/BIMMAKE/sdk/GmFamilyUpdate.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GmModelFamily.dll and C:/compare/BIMMAKE/sdk/GmModelFamily.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GmProcess.dll and C:/compare/BIMMAKE/sdk/GmProcess.dll differ
      Files C:/compare/BIMMAKE.old/sdk/GmValueValidator.dll and C:/compare/BIMMAKE/sdk/GmValueValidator.dll differ
      Files C:/compare/BIMMAKE.old/sdk/Hatch.dll and C:/compare/BIMMAKE/sdk/Hatch.dll differ
      Files C:/compare/BIMMAKE.old/sdk/LineType.dll and C:/compare/BIMMAKE/sdk/LineType.dll differ
      Files C:/compare/BIMMAKE.old/sdk/MaterialCore.dll and C:/compare/BIMMAKE/sdk/MaterialCore.dll differ
      Files C:/compare/BIMMAKE.old/sdk/MemoryChunkPager.dll and C:/compare/BIMMAKE/sdk/MemoryChunkPager.dll differ
      Only in C:/compare/BIMMAKE/sdk: Mesh.dll
      Only in C:/compare/BIMMAKE.old/sdk: QProfile.txt
      Files C:/compare/BIMMAKE.old/sdk/RegenCore.dll and C:/compare/BIMMAKE/sdk/RegenCore.dll differ
      Files C:/compare/BIMMAKE.old/sdk/RenderSystemAngle.dll and C:/compare/BIMMAKE/sdk/RenderSystemAngle.dll differ
      Files C:/compare/BIMMAKE.old/sdk/RenderSystemGL.dll and C:/compare/BIMMAKE/sdk/RenderSystemGL.dll differ
      Files C:/compare/BIMMAKE.old/sdk/RichText.dll and C:/compare/BIMMAKE/sdk/RichText.dll differ
      Files C:/compare/BIMMAKE.old/sdk/TopoEncoding.dll and C:/compare/BIMMAKE/sdk/TopoEncoding.dll differ
      Files C:/compare/BIMMAKE.old/sdk/ViewCore.dll and C:/compare/BIMMAKE/sdk/ViewCore.dll differ
      Files C:/compare/BIMMAKE.old/sdk/ViewManager.dll and C:/compare/BIMMAKE/sdk/ViewManager.dll differ
      Only in C:/compare/BIMMAKE.old/sdk: ViewerConfig.ini
      Only in C:/compare/BIMMAKE.old/sdk: algorithmLog.ini
      Only in C:/compare/BIMMAKE/sdk: boost_date_time-vc140-mt-x64-1_72.dll
      Files C:/compare/BIMMAKE.old/sdk/bson.dll and C:/compare/BIMMAKE/sdk/bson.dll differ
      Files C:/compare/BIMMAKE.old/sdk/common_utilities.dll and C:/compare/BIMMAKE/sdk/common_utilities.dll differ
      Only in C:/compare/BIMMAKE/sdk: cpprest140_2_10.dll
      Only in C:/compare/BIMMAKE/sdk: datacodes.json
      Only in C:/compare/BIMMAKE/sdk: enumcodes.json
      Files C:/compare/BIMMAKE.old/sdk/gdc_config.xml and C:/compare/BIMMAKE/sdk/gdc_config.xml differ
      Files C:/compare/BIMMAKE.old/sdk/jsoncpp.dll and C:/compare/BIMMAKE/sdk/jsoncpp.dll differ
      Files C:/compare/BIMMAKE.old/sdk/libcrypto-1_1-x64.dll and C:/compare/BIMMAKE/sdk/libcrypto-1_1-x64.dll differ
      Files C:/compare/BIMMAKE.old/sdk/libssl-1_1-x64.dll and C:/compare/BIMMAKE/sdk/libssl-1_1-x64.dll differ
      Only in C:/compare/BIMMAKE/sdk: propertycodes.json
      Files C:/compare/BIMMAKE.old/sdk/pugixml.dll and C:/compare/BIMMAKE/sdk/pugixml.dll differ
      Files C:/compare/BIMMAKE.old/sdk/zlib1.dll and C:/compare/BIMMAKE/sdk/zlib1.dll differ
      Only in C:/compare/BIMMAKE: sky_image
      Only in C:/compare/BIMMAKE: zh-CN
      Only in C:/compare/BIMMAKE: zh-TW
      

       

文件內容對比

在上面目錄對比過程中,如果兩邊文件都存在而只是內容不同,進入文件內容對比邏輯:

 1 # for windows command, parameter seperator is /
 2 # and bash will autoexpand to DRIVE:/
 3 # here use // to avoid expanding.
 4 $win32/dumpbin //disasm "$left" | sed '5d' > "$srcasm"
 5 
 6 # use sed '5d' to remove a line like :
 7 # Dump of file Bin1334\Release\GSUPService.exe
 8 # which disturb the diff result by writing dir name 
 9 # remove it !!
10 $win32/dumpbin //disasm "$right" | sed '5d' > "$dstasm"
11 
12 if [ $(cat "$srcasm" | wc -l) -gt 10 ] && [ $(cat "$dstasm" | wc -l) -gt 10 ]; then
13     # left & right are all valid PE format 
14     resp=$(diff -q "$srcasm" "$dstasm")
15     if [ $verbose != 0 ]; then 
16         echo "resp=$resp"
17     fi 
18 else
19     resp="non PE format differs"
20     echo "$resp"
21 fi
22 
23 if [ -z "$resp" ]; then 
24     echo -e "   $left \n== $right in asm, skip"
25 else
26     # need to replace
27     echo -e "   $left \n!= $right"
28     relpath=$(get_relative_path "$srcdir" "$left")
29     if [ -z "$relpath" ]; then 
30         echo "find relative path by source dir failed, try dest"
31         relpath=$(get_relative_path  "$dstdir" "$right")
32         if [ -z "$relpath" ]; then
33             echo "find relative path by dest dir failed, skip"
34             continue;
35         fi
36     fi
37 
38     if [ $verbose != 0 ]; then 
39         echo "relpath: $relpath"
40     fi 
41 
42     tarpath="$outdir/$setupdir$relpath"
43     copy_file "$right" "$tarpath"
44     itemcnt=$(($itemcnt+1))
45     if [ $exactmode != 0 ]; then 
46         # 1st argument represent zip folder
47         # 2nd argument represent install folder
48         # differs with copy order !
49         replace_item "$setupdir$relpath" "$relpath"
50     fi
51 fi

 

這裡需要考慮二進制可執行文件不能直接對比(同樣的代碼編譯兩次得到的可執行文件也不一樣,這是因為 PE 文件中包含了生成時間、唯一 ID 等與代碼無關的內容),因此需要將其先反編譯為彙編文本,再對彙編語句進行對比。這裡沒有通過文件後綴(dll / exe)來判斷是否為可執行文件,這是因為產品中總有一些 dll 有奇奇怪怪的後綴。這裡統一採用 dumpbin 進行反彙編,如果成功就是可執行文件;反之就是普通的文本或二進制文件。

  • 1-10:嘗試使用 dumpbin 進行反彙編(注意使用 //disasm 來傳遞 win32 命令選項,因為 msys2 會將單獨的 / 認為是根目錄從而自動進行擴展、是我們不想要的)。下面是反彙編成功後的輸出:
    Microsoft (R) COFF/PE Dumper Version 12.00.40629.0
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    
    
    File Type: DLL
    
      0000000180001000: 45 8B C0           mov         r8d,r8d
      ……
      000000018000E202: CC                 int         3
    
      Summary
    
            1000 .data
            1000 .pdata
            7000 .rdata
            1000 .reloc
            1000 .rsrc
            E000 .text
    

    可見 dumpbin 會輸出一個占 5 行的頭部信息,為了防止這個信息干擾後續的對比,這裡使用 sed 刪除前 5 行;

  • 12-21:如果舊文件與新文件反彙編結果行數都大於10,說明兩者都是可執行文件,去除前 5 行後進行反彙編內容的對比;否則是普通文件,不再進行對比(diff 已告訴我們它們不同)。下面是反彙編失敗時的輸出:
    $ win32/dumpbin //disasm  C:/compare/BIMMAKE/FillPatternFileApiTestData/right.pat
    Microsoft (R) COFF/PE Dumper Version 12.00.40629.0
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    
    Dump of file C:/compare/BIMMAKE/FillPatternFileApiTestData/right.pat
    C:/compare/BIMMAKE/FillPatternFileApiTestData/right.pat : warning LNK4048: Invalid format file; ignored
    
      Summary
    

    可以看到一共只有 9 行輸出,而一般成功的反彙編輸出少則上百行、多則上萬行,再少也不可能少於 10 行輸出;

  • 23-36:如果文件內容一樣,跳過此文件;否則需要確定當前文件在對比目錄中的相對路徑。先嘗試使用舊目錄去獲取,如果失敗再嘗試使用新目錄去獲取。這裡獲取相對目錄的工作交由 get_relative_path 這個函數來完成,出於對整體的把握,這裡不對這些細節展開介紹了;
  • 42-50:通過上面獲得的相對路徑,就可以在輸出目錄構建目標文件全路徑啦。複製文件的工作交由 copy_file 函數來完成,在內部它先創建對應的目錄,然後調用 cp 完成文件複製。如果用戶選擇了 exact 模式,則將為每項在配置文件中添加一條 json 格式的替換記錄 (通過 replace_item 函數),格式類似於下面這樣:
    {
      "type": "replace",
      "target": "/Teigha/ACCAMERA_20.8src_14.tx",
      "source": "setup/Teigha/ACCAMERA_20.8src_14.tx"
    },
    

     對於非 exact 模式可以直接將整個目錄遞歸覆蓋到目標區域,因而不需要一條條的添加 json 配置。

單個文件處理

在上面的目錄對比過程中,如果兩邊只有一個文件/目錄存在,進入單個文件/目錄處理邏輯:

 1 relpath=$(get_relative_path "$srcdir" "$dir")
 2 if [ ! -z "$relpath" ]; then 
 3     # need to remove 
 4     echo -e "only in  $srcdir: (old)\n         $dir/$file, \nrelpath: $relpath/$file"
 5     itemcnt=$(($itemcnt+1))
 6     # 1st argument represent install folder
 7     # differs with copy order !
 8     delete_item "$relpath/$file" $isdir
 9 else
10     relpath=$(get_relative_path "$dstdir" "$dir")
11     if [ ! -z "$relpath" ]; then 
12         # need to add
13         echo -e "only in  $dstdir: (new)\n         $dir/$file, \nrelpath: $relpath/$file"
14         copy_file "$dir/$file" "$outdir/$setupdir$relpath/$file"
15         itemcnt=$(($itemcnt+1))
16         if [ $exactmode != 0 ]; then 
17             # 1st argument represent zip folder
18             # 2nd argument represent install folder
19             # differs with copy order !
20             add_item "$setupdir$relpath/$file" "$relpath/$file" $isdir
21         fi
22     else
23         echo "unknown single file: $dir/$file"
24     fi
25 fi

如果單個文件項位於新目錄,則新增文件項;如果位於舊目錄,則刪除:

  • 1-8:計算單個文件項在舊目錄的相對路徑,如果結果不為空,表示文件項位於舊目錄,否則位於新目錄。刪除文件的工作交由 delete_item 函數完成,其實就是在配置文件中加入一條刪除記錄:
    {
      "type": "delete",
      "target": "/sdk/QProfile.txt"
    },
    

     如果是單獨的目錄,則遞歸刪除整個目錄:

    {
      "type": "delete_dir",
      "target": "/Share/ViewCoreResources/MaterialLibrary/textures/rainTextures"
    },
    

     刪除項是否添加是和 exact 模式無關的,因為目錄的遞歸覆蓋只能添加或替換文件,不能刪除。

  • 10-21:計算單個文件項在新目錄的相對路徑,此時結果一般是不為空的,調用 copy_file 函數複製新文件項到輸出目錄。當用戶選擇 exact 模式時,在配置文件中加入一條增加記錄 (通過 add_item):
    {
      "type": "add",
      "target": "/Teigha/GripPoints_20.8src_14.tx",
      "source": "setup/Teigha/GripPoints_20.8src_14.tx"
    },
    

    如果是單獨的目錄,則遞歸增加整個目錄:

    {
      "type": "add_dir",
      "target": "//Libraries",
      "source": "setup//Libraries"
    },
    

     copy_file 通過給 cp 傳遞 -r 選項,可以很好的支持目錄的遞歸拷貝。

生成配置文件

處理完各個文件和子目錄以後,就可以生成升級需要的配置文件啦:

 1 # remove temporary files
 2 if [ $verbose -eq 0 ]; then
 3     # only remove temporary files 
 4     # when not in verbose mode
 5     rm "$srcasm"
 6     rm "$dstasm"
 7     rm "$dirdiff"
 8 fi 
 9 
10 if [ $itemcnt -eq 0 ]; then 
11     echo "no item add/replace/delete found, stop generating..."
12     exit 1
13 fi 
14 
15 if [ $exactmode -eq 0 ]; then 
16     # not exact mode
17     # add setup dir totally
18     if [ -z "$reldir" ]; then 
19         jsonitem=$(echo "     {\n"\
20         "      \"type\": \"add_dir\",\n"\
21         "      \"target\": \".\",\n"\
22         "      \"source\": \"$setupdir\"\n"\
23         "    }")
24     else
25         jsonitem=$(echo "     {\n"\
26         "      \"type\": \"add_dir\",\n"\
27         "      \"target\": \"$reldir\",\n"\
28         "      \"source\": \"$setupdir\"\n"\
29         "    }")
30     fi
31 
32     if [ $verbose != 0 ]; then 
33         echo -e "$jsonitem"
34     fi
35 
36     if [ -z "$json" ]; then 
37         json="$jsonitem"
38     else 
39         json="$json,\n$jsonitem"
40     fi
41 fi 
42 
43 json="$jsonhead$json$jsontail"
44 echo -e "$json" > "$outdir/upgrade.json"
45 echo "upgrade.json created, $itemcnt items generated"
46 echo -e "$json"

由於之前在處理文件過程中已經將必要的配置信息生成好了,這裡的工作其實很簡單:

  • 2-8:如果指定 verbose 選項,則保留中間文件用於排錯,否則刪除;
  • 10-13:如果經過對比,沒有任何差異,或兩個目錄都是空的,導致輸出內容為空,則中止並退出整個打包腳本;
  • 15-41:非 exact 模式下,需要添加一條 add_dir 配置來將輸出目錄中的所有文件遞歸覆蓋到安裝目錄。如果用戶指定了只替換安裝目錄中的某個子目錄,這裡需要調整一下目標路徑(line 24-30);
  • 43-46:將各個 json 組裝成完整內容並生成到輸出目錄,名稱固定為 “upgrade.json”。

生成壓縮包

所有內容就緒後就可以壓縮成包上傳到後台啦:

 1 tarpath="$outdir/*"
 2 if [ "${tarpath/:/}" == "$tarpath" ]; then 
 3     # not contain ':', a relative path
 4     # prefix ./ to avoid generate root dir in 7z
 5     tarpath="./$tarpath"
 6 fi
 7 
 8 $win32/7z a "$setupdir.7z" "$tarpath"
 9 resp=$?
10 if [ -z "$setupdir.7z" ]; then 
11     echo "compressing failed: $resp"
12     exit 2
13 fi
14 
15 mv "$setupdir.7z" "$outdir/$setupdir-$version-$sp.7z"
16 #echo "create 7zip compress packet OK"
17 exit 0

 

這裡沒有使用 tar cvzf 來生成 setup.tar.gz 文件,因為升級客戶端只能接收 7z 格式的壓縮包,這裡使用 win32 版本的 7z 命令執行壓縮過程。從另外的角度來講,7z 壓縮算法也是目前壓縮率最高的算法,可以有效的降低網絡傳輸的流量(7z 壓縮率親測高於 zip 及 gz)。這段代碼比較簡單,就不展開講解了,最後會生成下面這樣的文件結構:

$ ls -lhrt
total 348M
drwxr-xr-x 1 yunh 1049089    0 11月 17 19:18 setup/
-rw-r--r-- 1 yunh 1049089 147K 11月 17 19:19 upgrade.json
-rw-r--r-- 1 yunh 1049089 348M 11月 17 19:19 setup-1.8.0.0-0.7z

所有需要添加和替換的文件都會被放在 setup 目錄下,這樣在遞歸替換時就可以避免將無關文件(例如 upgrade.json)替換到安裝目錄。生成的壓縮包命名方式為:setup-version-sp.7z。非 exact 模式生成的配置文件內容如下:

{
  "version": "1.8.0.0",
  "sp": "0",
  "actions": 
  [
     {
       "type": "delete",
       "target": "//BmRecentDocumentPathRecord.xml"
     },
     {
       "type": "delete",
       "target": "/BmWelcomeTemplateFile/小別墅.gbp"
     },
     {
       "type": "delete",
       "target": "/BmWelcomeTemplateFile/小別墅.png"
     },
     {
       "type": "delete",
       "target": "/BmWelcomeTemplateFile/老虎窗屋頂.gbp"
     },
     {
       "type": "delete",
       "target": "/BmWelcomeTemplateFile/老虎窗屋頂.png"
     },
     {
       "type": "delete",
       "target": "/CadIdentifier/DBErrorReport.txt"
     },
     {
       "type": "delete",
       "target": "//GPUDriverConfig.ini"
     },
     {
       "type": "delete",
       "target": "//MjLicense.dll"
     },
     {
       "type": "delete",
       "target": "//MjRichTextEditor.dll"
     },
     {
       "type": "delete",
       "target": "//MjUIArchitecture.dll"
     },
     {
       "type": "delete",
       "target": "//Packing4Rendering.dll"
     },
     {
       "type": "delete",
       "target": "//QProfile.txt"
     },
     {
       "type": "delete",
       "target": "//RecentDocumentPathRecord.xml"
     },
     {
       "type": "delete",
       "target": "//ViewerConfig.ini"
     },
     {
       "type": "delete",
       "target": "//algorithmLog.ini"
     },
     {
       "type": "delete",
       "target": "//gdpcore.1.txt"
     },
     {
       "type": "delete",
       "target": "//gdpcore.txt"
     },
     {
       "type": "delete",
       "target": "/sdk/QProfile.txt"
     },
     {
       "type": "delete",
       "target": "/sdk/ViewerConfig.ini"
     },
     {
       "type": "delete",
       "target": "/sdk/algorithmLog.ini"
     },
     {
       "type": "add_dir",
       "target": ".",
       "source": "setup"
     }
  ]
}

 所有新增及替換操作,全在最後一條 add_dir 配置項了。如果是 exact 模式的話,配置文件就會大很多了,它會針對每個新增、替換項生成一個類似上面刪除項的條目,這裡就不多做演示了。

用戶圖形界面

上面的腳本只能通過命令行界面 (CUI) 調用,那能不能將它嵌入到用戶圖形界面 (GUI) 呢?答案是可以的。

 

上面這個程序是真的只做了界面。在獲取用戶完整輸入後,它創建了一個匿名管道 (CreatePipe),並將管道的一端作為新進程的標準輸出 (stdout)、同時用參數構造新進程的命令行 (上面的腳本 diffpacker.sh 作為第一參數) 來啟動 bash.exe 進程。當腳本在運行中產生輸出時,程序通過匿名管道讀取這些輸出,並將它們重定向到 UI 底部的輸出框,達到實時查看腳本輸出的效果。

下載

由於不涉及到後台接口,這個小工具中的腳本、調用到的命令及圖形界面源碼和可執行程序都是可以完整下載的://files.cnblogs.com/files/goodcitizen/diffpacker.zip

有類似需求的同學,改改腳本就可以用啦。其中用到了 msys2,它是一個運行在 windows 上的 bash,我們常用的 git 就使用它作為 git bash 的技術支撐。之前我的不少文章也都涉及過它:

查看博客園積分與排名趨勢圖的工具 》、《用 shell 腳本做 restful api 接口監控 》、《用 shell 腳本做日誌清洗 》,感興趣的可以參考一下。

下面是 msys2 的主頁,可以從這裡獲取 Windows 上的安裝包://www.msys2.org/

後記

這個小工具後來在業務線得到了廣泛使用,在某個大產品使用過程中還引發了一次血案,關於該案,我現在給大家梳理一下:

產品組有兩個 dll 分別封裝了基類 (base.dll) 和派生類 (derived.dll);有一次產品組為基類添加了兩個成員作為補丁版本,在 diff 過程中成功的識別出了 base.dll 被修改,但是沒有將 derived.dll 識別出來,然後就這樣沒有經由本地驗證就向外發佈了;結果導致打過補丁的版本一啟動就崩潰了,原因是 derived.dll 中舊的派生類和 base.dll 中新的基類二進制不兼容了。

後來他們通過緊急補丁修復了上述問題,在後面復盤問題的過程中,我手動檢查了腳本的運行日誌,發現確實沒有識別出新舊 derived.dll —— 腳本認為它們是二進制相同的。後來查詢了一些相關資料,了解到我的 dumpbin /disasm 只是反編譯了可執行文件中的代碼段,而其它一些段 (例如數據段) 則被遺漏了。上面這個例子中,父類的成員變化後,肯定會有相應的 section 會做出調整,但是我通過調整 dumpbin 的選項也沒有對比出這個段在哪裡。後來嘗試使用 msys2 自帶的 objdump 命令去反編譯,它確實可以得到更豐富的內容,從而判斷出新舊 derived.dll 是不同的,但驗證同一段相同代碼編譯兩次生成的 dll 進行對比時,它仍然會告訴我兩個 dll 不同!所以我不能簡單的使用 objdump 替換 dumpbin,因為如果它報告所有 dll 都不同的話,這實際上就沒有意義了。最後,這段代碼還是帶着 bug 繼續「上崗」了,產品組現在多了一個心眼兒,每次生成 patch 後都會親自做一下驗證。

這個故事從側面說明之前產品組對我的工具的信任程度 —— 那是毫無保留信任啊,哈哈。然而我做這個小工具花了多長時間呢?其實也就一周左右,而且有很多時間是花費在調試 windows 與 shell 的一些不兼容之處,真正寫業務代碼也就不到一周。如果換作用 c++ 來寫呢,我恐怕沒有一個月是搞不定的了,這就是使用現成組件「搭積木」帶來的效率優勢。而 shell 作為各個命令之間的粘合劑,為實現這種裝配式的開發提供了必要的支撐。現在回頭來看 linux 的設計哲學 —— 「有眾多單一目的的小程序,一個程序只實現一個功能,多個程序組合完成複雜任務」 —— 的的確確是一個法寶啊。