從高斯windows下的批量執行談DOS批處理文件
這是個老生常談的問題,但通過DOS批處理文件,可以實現很多方便的功能,想在這里多說一下。
先從最簡單的解決方法說,網上老是有人問,我以前也回答過多次。windows下高斯批量執行有三種方法
1 多個輸入文件寫入一個列表中,統一執行:創建.bcf文件,每一行都是C:\QCexperiment\exp3\b1.gjf , b1.out這樣。沒用的行開頭寫!注釋掉。用gaussian打開此文件后,蹦出來的窗口先exit,然后點三角箭頭開始運行。也可以用gaussian的Utilities-edit batch list來編輯批處理任務列表,可保存成.bcf。這個方法一個著名的問題是其中一個任務出錯,整個批處理就會斷掉。其實上可以在G03W界面的file-preference-Process里面設定來解決,將默認的"End Batch Run on Error"去掉,則運行中某任務出錯將繼續執行下面的任務。"Prompt Message"如果去掉的話,批量運行過程中將不再出現任何對話框,例如是否覆蓋以前輸出文件之類將不再提示,適合無人看管的情況下批量執行。
2 多個工作寫入一個文件中,統一執行:寫一個輸入文件,里面用例如--Link1--隔開。實際就是那個addition step方法創建的。這種方式適合多個任務有明顯相關性的時候,將它們和在一起。
3 用簡單批處理文件完成多個任務
首先在系統-高級-環境變量里,在系統變量的PATH里面把g03的路徑添加到里面,再新增GAUSS_EXEDIR環境變量也設定為g03的所在路徑。這樣任何目錄下都可以運行g03命令了
比如在gaussian03W文件夾里面建立一個批處理文件k.bat
如果要自動計算d:\study\2.gjf和d:\study\3.gjf兩個文件,然后將結果生成到e:\下面,分別叫2p.out和3p.out,那么bat文件里就寫:
g03 d:\study\2 e:\2p
g03 d:\study\3 e:\3p
然后運行k.bat就可以自動計算了,只是看不到運行過程。注意別寫后綴名,.gjf和.out不用寫,自動默認讀取.gjf和生成.out。如果不寫輸出文件的路徑,就默認成生成和gjf同文件名的out文件在原gjf文件夾里(我現在用的E01里面寫清楚輸入和輸出文件名的擴展名也可以運行,比如g03 1.gjf 1.out)。
使用這種方法,若某個.gjf運行失敗,將自動繼續運行接下來的.gjf,不會因此出錯停住。
以上是最一般的方法,但是有時候需要運用類似linux的shell script來實現一些高級功能,比如執行當前文件夾所有.gjf。
最簡單的方法是編寫一個批處理文件k.bat,內容是:
for /f %%i in ('dir *.gjf /b') do g03 %%~ni %%~ni
然后輸入k來執行,當前目錄下所有.gjf都被運行,輸出的.out文件文件名與.gjf相同。
for ... in ... do就是循環,/f指的是將%%i依次賦值為in后面()里面的內容,括號里面可以是一個文件,也可以是一條指令,如果是指令,需用'括起來。
dir /b指的是只顯示文件名(包括擴展名),不顯示文件的其它信息
%%i就是循環過程中的變量,在循環中被賦值為一個個.gjf文件。前面提到了g03后面輸入輸出文件不要加擴展名,%%~ni是將%%i的.gjf后綴去掉的結果。比如%%i是c60.gjf,%%~ni就是c60。
運用batch script,還可以實現更高級的功能,比如想輸出每個文件運行的結果,以及運行結束的時間,可以這么寫批處理文件:
@echo off
setlocal enabledelayedexpansion
for /f %%i in ('dir *.gjf /b') do (
g03 %%~ni %%~ni&if !errorlevel!==0 (
echo Calculation of %%i finished at !date! !time!) else (
echo Calculation of %%i failed at !date! !time!))
echo off想必大家知道,可以用來屏蔽接下來運行的指令。@就是讓echo off本身不顯示。
echo大家也都知道,就是顯示文字,也可以顯示變量。
其中%%~ni&if里面的&用來將前面的語句和后面的語句連接,執行完&前面的語句再運行后面的語句。DOS批處理文件一個很不方便之處是do后面只能有一條語句,如果需要運行很多條指令,必須用&把它們連起來組成一條語句。如果為了看起來清楚需要換行,必須在括號的位置換行。
errorlevel變量指的是程序返回代碼,前面的指令運行成功就是0,錯誤就是非0。
其中用到了分支語句if a==b (...) else (...)
date和time環境變量是系統預置的,實時更新,內容分別是日/月/年和小時/分鐘/秒/毫秒。
批處理程序中的變量主要有4種,
一種是%1 %2 %3這樣的,比如運行k.bat 3 8 5,那么這三個變量分別等于3 8 5,%0是自身
一種是%i%這樣的,這是最普通的,可以用set設定,比如set i=5,調用時候就是%i%,比如echo %i%
一種是%%i這樣的,用在隨循環而變化的變量,例子中的%%i就是典型。它不斷根據in后面的內容被賦值。
一種是用!括住的,比如!errorlevel!。為何要用!errorlevel!而不用%errorlevel%呢?
這個問題是時間延遲問題,批處理文件中默認情況下,只有每運行完一條語句才更新一次變量的值,比如
set i=5
set i=3 & echo %i%
顯示出來的是5而不是3,因為set i=3 & echo %i%是一整條語句,設置i=3之后并沒有立刻生效,所以顯示的%i%還是上面那條語句設的5。
這是批處理文件和其它語言的一個很顯著差別。為了避免這種情況,需要加上setlocal enabledelayedexpansion。這樣之后用!括住的變量數值都是使用即時的值。比如上面例子改成set i=3 & echo !i!,那么得到的就是3而不是5。
之所以要用!errorlevel!,就是使這個errorlevel變量是真正的它的&前面那句g03 %%~ni %%~ni返回碼而非以前的。同理!date!和!time!都是為了得到當前真正的日期和時間。如果不這么設,運行結果會判斷錯誤,而且每一條輸入文件完成日期和時間都是一樣的。
這樣,把上面那條批處理腳本拷貝進all.bat,把它放進一個文件夾,文件夾里包含360.gjf,c60.gjf,vv60.gjf,xc0.gjf,其中360.gjf輸入文件有誤。運行all,得到:
Calculation of 360.gjf failed at 01/11/2008 2:17:27.91
Calculation of c60.gjf finished at 01/11/2008 2:17:35.97
Calculation of vv60.gjf finished at 01/11/2008 2:17:44.07
Calculation of xc0.gjf finished at 01/11/2008 2:17:52.10
看,不錯吧。運行結果和時間一目了然,很適合執行大批量任務。
實際上很多人忽視了DOS的批處理文件的強大功能,令人心寒啊。由于windows的GUI做得太好了,DOS命令恐怕現在熟悉的人已經越來越少了,至少可以說,世界上所有人的大腦里,關于DOS的知識失去得比增加得快。windows平臺搞計算模擬的人熟練使用DOS批處理文件的人很少,而在linux平臺上搞計算模擬的人不得不使用文本控制臺(光靠linux的GUI干不了什么大事,某些廉價計算機預裝linux給菜鳥用,簡直是笑話),以為shell script是甚至獨一無二的法寶,加上linux內置的繁多的命令,認為是windows平臺遠不能及的。DOS批處理腳本,雖然在一定程度上比不上linux的shell script,但是足以實現絕大多數它的功能。甚至說到上面那個高斯windows下批處理運行的問題,有人以為這是windows下絕對做不成的事,說用什么bash for windows,真是舍近求遠。DOS批處理文件在某些地方用得還是很廣泛的,比如hei客,這是必會的。還有一些某些人認為方便的裝機工具,比如番茄花園之流也用這些。以及一些別有用心的人,verycd上renchongyi是個典型,篡改別人辛辛苦苦破解的程序,通過批處理文件自動運行一堆病毒,號稱是安裝程序欺騙菜鳥,這是非常卑鄙的。
總之,重拾DOS,重視起批處理文件吧!