修改正在執行的Batch

這陣子寫了隻外掛程式,希望能簡單的透過batch做線上更新。在執行batch去解壓縮並覆蓋所有內容後(當然包含更新batch本身),batch並沒正常的執行完成。以下是我的script:

rem 前略..
 
"%ZIP_CMD%" x -y -o"%TEMP_DIR%" Bot.zip
xcopy /i /e /y "%TEMP_DIR%"
 
del /f Bot.zip
exit 0
在複製檔案(xcopy)後,並沒執行刪除動作。也許你會說: 那幹嘛更新這隻batch? 更新batch也是可能有變動的,我又懶得寫另外一隻程式替我處理更新問題。之前曾做過修改batch中jvm的功能,也有遇到

正在執行的batch被修改後,非常有可能會造成接下的執行不正常。我假設「Batch是做到哪裡讀到哪裡的行為」,於是我寫了兩隻測試Batch來替我驗證這假設是否成立。

  1. test.bat: 複製test_tmp.bat取代自己。
  2. test_tmp.bat: 一堆echo。

test.bat:

@echo off
 
set BASE=%~dp0
 
cp -f "%BASE%test_tmp.bat" "%BASE%test.bat"
test_tmp.bat:
@echo off
 
set BASE=%~dp0
echo long~long~long~long~long~long~long~long~long~long~string
echo long~long~long~long~long~long~long~long~long~long~string
 
echo 123
echo 456
先看看執行結果在做解釋:

cp -f "%BASE%test_tmp.bat" "%BASE%test.bat"
echo long~long~long~long~long~long~long~long~long~long~string
從test.bat與test_tmp.bat的第三行做比較可以驗證我的假設: 「Batch以行為單位,讀到哪做到哪。」 從test.bat結束位置對照到test_tmp.bat的echo內容,你也許會問說: 不是應該從g~long~long~string開始嗎? 這個問題就讓大家自行思考了。

我想到的解法是: 「修改後就結束Batch的執行。」 我們可以透過&exit達成。直接看看範例:

@echo off
 
set BASE=%~dp0
 
cp -f "%BASE%test_tmp.bat" "%BASE%test.bat" &  exit /b 0
 
rem cp -f "%BASE%test_tmp.bat" "%BASE%test.bat" & if exist "%BASE%test.bat" echo exist &  exit /b 0
我將exit動作接在複製batch後面,也可以將其它後續動作透過&串起來。這個寫法的壞處是: 可讀性不佳。但如果再改一下寫法用^做跳行就會好看些:
@echo off
 
set BASE=%~dp0
 
cp -f "%BASE%test_tmp.bat" "%BASE%test.bat" &^
exit /b 0

友藏內心獨白: 怪怪問題不要來!