Windows批處理檔案

jinqibingl發表於2012-10-04

Windows批處理檔案  

Windows批處理檔案

【 一、什麼是批處理 】

 批處理(Batch),也稱為批處理指令碼。顧名思義,批處理就是對某物件進行批次的處理。批處理檔案的副檔名為 bat 。
  目前比較常見 的批處理包含兩類:DOS批處理和PS批處理。PS批處理是基於強大的圖片編輯軟體Photoshop的,用來批次處理圖片的指令碼;而DOS批處理則是基 於DOS命令的,用來自動地批次地執行DOS命令以實現特定操作的指令碼。這裡要講的就是DOS批處理。
  批處理是一種簡化的指令碼語言,它應用於DOS和Windows系統中,它是由DOS或者 Windows系統內嵌的命令直譯器(通常是COMMAND.COM或者CMD.EXE)解釋執行。類似於Unix中的Shell指令碼。批處理檔案具 有.bat或者.cmd的副檔名,其最簡單的例子,是逐行書寫在命令列中會用到的各種命令。更復雜的情況,需要使用if,for,goto等命令控制程式 的執行過程,如同C,Basic等中高階語言一樣。如果需要實現更復雜的應用,利用外部程式是必要的,這包括系統本身提供的外部命令和第三方提供的工具或 者軟體。批處理檔案,或稱為批處理程式,是由一條條的DOS命令組成的普通文字檔案,可以用記事本直接編輯或用DOS命令建立,也可以用DOS下的文字編 輯器Edit.exe來編輯。在“命令提示”下鍵入批處理檔案的名稱,或者雙擊該批處理檔案,系統就會呼叫Cmd.exe執行該批處理程式。一般情況下, 每條命令佔據一行;當然也可以將多條命令用特定符號(如:&、&&、|、||等)分隔後寫入同一行中;還有的情況就是像if、 for等較高階的命令則要佔據幾行甚至幾十幾百行的空間。系統在解釋執行批處理程式時,首先掃描整個批處理程式,然後從第一行程式碼開始向下逐句執行所有的 命令,直至程式結尾或遇見exit命令或出錯意外退出。


【 二、簡單批處理命令簡介 】

  【 echo 命令 】
  開啟回顯或關閉請求回顯功能,或顯示訊息。如果沒有任何引數,echo 命令將顯示當前回顯設定。
  語法
  echo [{on|off}] [message]
  Sample:@echo off / echo hello world
  在實際應用中我們會把這條命令和重定向符號(也稱為管道符號,一般用> >> ^)結合來實現輸入一
  些命令到特定的檔案中。
  【 rem 命令 】
  註釋命令,類似於在C語言中的/*--------*/,它並不會被執行,只是起一個註釋的作用,便於別人閱讀
  和你自己日後修改。
  Rem Message
  Sample:@Rem Here is the description.
  【 pause 命令 】
  暫停命令。執行 Pause 命令時,將顯示下面的訊息:
  Press any key to continue. . .(或:請按任意鍵繼續. . .)
  Sample:
  @echo off
  :begin
  copy G:*.* d:\back
  echo 請插入另一張光碟...
  pause
  goto begin
  在這個例子中,驅動器 G 中磁碟上的所有檔案均複製到d:\back中。顯示的註釋提示您將另一張光碟
  盤放入驅動器 G 時,pause 命令會使程式掛起,以便您更換光碟,然後按任意鍵繼續處理。
  【 call 命令 】
  從一個批處理程式呼叫另一個批處理程式,並且不終止父批處理程式。call 命令接受用作呼叫目標的
  標籤。如果在指令碼或批處理檔案外使用 Call,它將不會在命令列起作用。
  語法
  call [[Drive:][Path] FileName ] [:label [arguments]]
  引數
  [Drive:}[Path] FileName
  指定要呼叫的批處理程式的位置和名稱。
  【 start 命令 】
  呼叫外部程式,所有的DOS命令和命令列程式都可以由start命令來呼叫。
  如:start calc.exe 即可開啟Windows的計算器。
  常用引數:
  MIN 開始時視窗最小化
  SEPARATE 在分開的空間內開始 16 位 Windows 程式
  HIGH 在 HIGH 優先順序類別開始應用程式
  REALTIME 在 REALTIME 優先順序類別開始應用程式
  WAIT 啟動應用程式並等候它結束
  parameters 這些為傳送到命令/程式的引數
  執行的應用程式是 32-位 GUI 應用程式時,CMD.EXE 不等應用程式終止就返回命令提示。如果在命令
  指令碼內執行,該新行為則不會發生。
  【 goto 命令 】
  跳轉命令。程式指標跳轉到指定的標籤,從標籤後的第一條命令開始繼續執行批處理程式。
  語法:goto label (label是引數,指定所要轉向的批處理程式中的行。)
  Sample:
  if {%1}=={} goto noparms
  if {%2}=={} goto noparms(如果這裡的if、%1、%2你不明白的話,先跳過去,後面會有詳細的解釋
  。)
  @Rem check parameters if null show usage
  :noparms
  echo Usage: monitor.bat ServerIP PortNumber
  goto end
  標籤的名字可以隨便起,但是最好是有意義的字母啦,字母前加個:用來表示這個字母是標籤,goto
  命令就是根據這個:來尋找下一步跳到到那裡。最好有一些說明這樣你別人看起來才會理解你的意圖啊。
  【 set 命令 】
  顯示、設定或刪除變數。
  顯示變數:set 或 set s 前者顯示批處理當前已定義的所有變數及其值,後者顯示所有以s開頭的變數及值。
  設定變數:set aa=abcd 此句命令便可向變數aa賦值abcd。如果變數aa已被定義,則aa的值被修改為abcd;若aa尚未定義,則此句命令即可定義新的變數aa,同時為變數aa賦予初始值abcd。
  刪除變數:set aa= 此句命令即可刪除變數aa。若變數aa已被定義,則刪除變數aa;若aa尚未定義,則此句命令為實質意義。
  需要說明的是,批處理中的變數是不區分型別的,不需要像C語言中的變數那樣還要區分int、float、char等。比如執行set aa=345後,變數aa的值既可以被視為數字345,也可以被視為字串345。
  set命令具有擴充套件功能,如用作互動輸入、字串處理、數值計算等,屬於高階命令範疇。


【 三、批處理符號簡介 】

  【 回顯遮蔽 @ 】
  表示不顯示@後面的命令,在入侵過程中(例如使用批處理來格式化敵人的硬碟)自然不能讓對方看到你使用的命令啦。
  @用法舉例:透過執行批處理檔案對比pause和@pause命令即可明瞭@的效果。
  【 重定向1 >與>> 】
  將輸出資訊重定向到指定的裝置或檔案。系統預設輸出到顯示器。
  如:echo aaaaa>a.txt 即可將本在顯示器上顯示的資訊aaaaa輸出到檔案a.txt中,螢幕上沒有任何顯示。如果檔案a.txt本來已經存在,該命令將首先擦除a.txt中的 所有資訊,然後寫入資訊aaaaa;若a.txt本來就不存在,該命令即可新建一個a.txt檔案,並寫入資訊aaaaa。
  echo aaaaa>>a.txt 類似於echo aaaaa>a.txt。區別在於:如果a.txt本已存在,>a.txt會擦除a.txt中的原有內容,而>>a.txt並不 擦除原有內容,僅在a.txt檔案的末尾新增資訊aaaaa。a.txt不存在時,二者沒有差別。
  【 重定向2 < 】
  將輸入資訊來源重定向為指定的裝置或檔案。系統預設從顯示器讀取輸入資訊。
  重定向使用舉例:
  =========================================
  @echo off
  echo abcdefg——這是檔案a.txt中的資訊>a.txt
  echo 請任意輸入字元,以回車結束:
  set /p ifo=
  cls
  echo 【 從螢幕獲得的輸入資訊 】
  echo %ifo%
  set /p ifo=  echo 【 從檔案a.txt獲得的輸入資訊 】
  echo %ifo%
  pause>nul
  =========================================
  讀者觀察命令與輸出即可體會到重定向的功能和效果。
  【 管道符號 | 】
  將管道符號前面命令的輸出結果重定向輸出到管道符號後面的命令中去,作為後面命令的輸入。使用格式為:command_1|command_2
  管道符號使用舉例:
  =========================================
  @echo off
  echo aaaa>a.txt
  del /p a.txt
  pause
  =========================================
  @echo off
  echo aaaa>a.txt
  echo y|del /p a.txt
  pause
  =========================================
  對比以上兩個批處理執行結果,讀者即可明白管道符的用法和效果。
  需要說明的是,上面del命令新增開關/p只是為了讓讀者明白管道符號的使用方法,實際刪除檔案時不加/p開關即可實現無提示直接刪除。
  【 轉義符 ^ 】
  將特殊符號轉化為一般符號,即剝離特殊符號的特殊地位。特殊符號指:| & > <
  比如,如果我們想輸出符號“>”,直接用命令 echo > 是不行的,必須修改為 echo ^> 。其餘幾個特殊符號類似需要有同樣的處理。
  跳脫字元使用舉例:
  =========================================
  @echo off
  echo aaaa>a.txt
  echo 第一句echo執行完畢
  echo aaaa^>a.txt
  echo 第二句echo執行完畢
  pause
  =========================================
  比較上面的兩句echo,第一句echo將資訊aaaa輸出到了檔案a.txt,而第二句echo則在直接螢幕上顯示除aaaa>a.txt
  【 邏輯命令符 】
  邏輯命令符包括:&、&&、||
  &-無條件執行&符號後面的命令;
  &&-當&&前面的命令成功執行時,執行&&後面的命令,否則不執行;
  ||-當||前面的命令失敗時,執行||後面的命令,否則不執行。
  =========================================
  @echo off
  echo ^|^|
  reg add HKCU /v try /f||echo **成功**
  reg add HKCU1 /v try /f||echo **失敗**
  echo ^&^&
  reg delete HKCU /v try /f&&echo **成功**
  reg delete HKCU /v try /f&&echo **失敗**
  echo ^&
  reg delete HKCU /v try /f&echo **成功**
  reg delete HKCU /v try /f&echo **失敗**
  pause
  =========================================
  執行reg add或reg delete後,系統會給出執行結果;我們透過echo命令也給出了“執行結果”。對比系統和我們自己給出的結果,既可以驗證邏輯命令的判斷機理。


【 四、常用DOS命令 】

  【 資料夾管理 】
  cd 顯示當前目錄名或改變當前目錄。
  md 建立目錄。
  rd 刪除一個目錄。
  dir 顯示目錄中的檔案和子目錄列表。
  tree 以圖形顯示驅動器或路徑的資料夾結構。
  path 為可執行檔案顯示或設定一個搜尋路徑。
  xcopy 複製檔案和目錄樹。
  【 檔案管理 】
  type 顯示文字檔案的內容。
  copy 將一份或多份檔案複製到另一個位置。
  del 刪除一個或數個檔案。
  move 移動檔案並重新命名檔案和目錄。(Windows XP Home Edition中沒有)
  ren 重新命名檔案。
  replace 替換檔案。
  attrib 顯示或更改檔案屬性。
  find 搜尋字串。
  fc 比較兩個檔案或兩個檔案集並顯示它們之間的不同
  【 網路命令 】
  ping 進行網路連線測試、名稱解析
  ftp 檔案傳輸
  net 網路命令集及使用者管理
  telnet 遠端登陸
  ipconfig顯示、修改TCP/IP設定
  msg 給使用者傳送訊息
  arp 顯示、修改區域網的IP地址-實體地址對映列表
  【 系統管理 】
  at 安排在特定日期和時間執行命令和程式
  shutdown立即或定時關機或重啟
  tskill 結束程式
  taskkill結束程式(比tskill高階,但WinXPHome版中無該命令)
  tasklist顯示程式列表(Windows XP Home Edition中沒有)
  sc 系統服務設定與控制
  reg 登錄檔控制檯工具
  powercfg控制系統上的電源設定
  對於以上列出的所有命令,在cmd中輸入命令+/?即可檢視該命令的幫助資訊。如find /?


【 五、語句結構 】

  類似於C語言,批處理也有它的語句結構。批處理的語句結構主要有選擇結構(if語句)、迴圈結構(for語句)等。
  【 if語句(選擇結構) 】
  if語句實現條件判斷,包括字串比較、存在判斷、定義判斷等。透過條件判斷,if語句即可以實現選擇功能。
  1、字串比較
  if語句僅能夠對兩個字元(串)是否相同、先後順序進行判斷等。其命令格式為:
  IF [not] string1 compare-op string2 command1 [else command2]
  其中,比較運算子compare-op有以下幾類:
  == - 等於
  EQU - 等於
  NEQ - 不等於
  LSS - 小於
  LEQ - 小於或等於
  GTR - 大於
  GEQ - 大於或等於
  選擇開關/i則不區分字串大小寫;選擇not項,則對判斷結果進行邏輯非。
  字串比較示例:
  ===============================================
  @echo off
  set str1=abcd1233
  set str2=ABCD1234
  if %str1%==%str2% (echo 字串相同!) else (echo 字串不相同!)
  if /i %str1% LSS %str2% (echo str1^=str2)
  echo.
  set /p choice=是否顯示當前時間?(y/n)
  if /i not %choice% EQU n echo 當前時間是:%date% %time%
  pause>nul
  ===============================================
  對於最後一個if判斷,當我們輸入n或N時的效果是一樣的,都不會顯示時間。如果我們取消開關/i,則輸入N時,依舊會顯示時間。
  另外請注意一下幾個細節:1-echo str1^=str2;2-echo.。
  2、存在判斷
  存在判斷的功能是判斷檔案或資料夾是否存在。其命令格式為:
  IF [NOT] EXIST filename command1 [else command2]
  ===============================================
  @echo off
  if exist %0 echo 檔案%0是存在的!
  if not exist %~df0 (
  echo 資料夾%~df0不存在!
  ) else echo 資料夾%~df0存在!
  pause>nul
  ===============================================
  這裡注意幾個地方:
  1-存在判斷既可以判斷檔案也可以判斷資料夾;
  2-%0即代表該批處理的全稱(包括驅動器磁碟機代號、路徑、檔名和擴充套件型別);
  3-%~df0是對%0的修正,只保留了其驅動器磁碟機代號和路徑,詳情請參考for /?,屬高階批處理範疇;
  4-注意if語句的多行書寫,多行書寫要求command1的左括號必須和if在同一行、 else必須和command1的右括號同行、command2的左括號必須與else同行、command1和command2都可以有任意多行,即 command可以是命令集。
  3、定義判斷
  定義判斷的功能是判斷變數是否存在,即是否已被定義。其命令格式為:
  IF [not] DEFINED variable command1 [else command2]
  存在判斷舉例:
  ===============================================
  @echo off
  set var=111
  if defined var (echo var=%var%) else echo var尚未定義!
  set var=
  if defined var (echo var=%var%) else echo var尚未定義!
  pause>nul
  ===============================================
  對比可知,"set var="可以取消變數,收回變數所佔據的記憶體空間。
  【 for語句(迴圈結構) 】
  for語句可以實現類似於C語言裡面的迴圈結構,當然for語句的功能要更強大一點,透過不同的開關可以實現更多的功能。for語句有多個開關,不同開關將會實現不同的功能。
  1、無開關
  無開關的for語句能夠對設定的範圍內進行迴圈,是最基本的for迴圈語句。其命令格式為:
  FOR %%variable IN (set) DO command
  其中,%%variable是批處理程式裡面的書寫格式,在DOS中書寫為%variable,即只有一個百分號(%);set就是需要我們設定的迴圈範圍,類似於C語言裡面的迴圈變數;do後面的command就是迴圈所執行的命令,即迴圈體。
  無開關for語句舉例:
  ===============================================
  @echo off
  for %%i in (a,"b c",d) do echo %%i
  pause>nul
  ===============================================
  2、開關/L
  含開關/L的for語句,可以根據set裡面的設定進行迴圈,從而實現對迴圈次數的直接控制。其命令格式為:
  FOR /L %%variable IN (start,step,end) DO command
  其中,start為開始計數的初始值,step為每次遞增的值,end為結束值。當end小於start時,step需要設定為負數。
  含開關/L的for語句舉例(建立5個資料夾):
  ===============================================
  @echo off
  for /l %%i in (1,2,10) do md %%i
  pause
  ===============================================
  上例將新建5個資料夾,資料夾名稱依次為1、3、5、7、9。可以發現,%%i的結束值並非end的值10,而是不大於end的一個數。
  3、開關/F
  含開關/F的for語句具有最強大的功能,它能夠對字串進行操作,也能夠對命令的返回值進行操作,還可以訪問硬碟上的ASCII碼檔案,比如txt文件等。其命令格式為:
  FOR /F ["options"] %%variable IN (set) DO command
  其中,set為("string"、'command'、file-set)中的一 個;options是(eol=c、skip=n、delims=xxx、tokens=x,y,m-n、usebackq)中的一個或多個的組合。各選 項的意義參見for /f。一般情況下,使用較多的是skip、tokens、delims三個選項。
  含開關/F的for語句舉例:
  ===============================================
  @echo off
  echo **No Options:
  for /f %%a in ("1,2,10") do echo a=%%a
  echo **Options tokens ^& delims:
  for /f "tokens=1-3 delims=," %%a in ("1,2,10") do echo a=%%a b=%%b c=%%c
  pause
  ===============================================
  @echo off
  echo 本資料夾裡面的檔案有:
  for /f "skip=5 tokens=3* delims= " %%a in ('dir') do (
  if not "%%a"=="

" if not "%%b"=="位元組" if not "%%b"=="可用位元組" echo %%b
  )
  pause
  ===============================================
  @echo off
  echo 本資料夾裡面的檔案有:
  dir>c:\file.txt
  for /f "skip=5 tokens=3* delims= " %%a in (c:\file.txt) do (
  if not "%%a"=="" if not "%%b"=="位元組" if not "%%b"=="可用位元組" echo %%b
  )
  del c:\file.txt
  pause
  ===============================================
  對於後面的兩個例子,其中options裡面的delims= 是可以刪除的,因為只要新增了/F開關係統就將delims的值預設為空格。
  符號字串中的最後一個字元星號,
  那麼額外的變數將在最後一個符號解析之後
  分配並接受行的保留文字。本例中也可以改為4,不過檔名中有空格的檔案,只能顯示空格以前部分
   同時我們也看到了,for語句的do後面的command也是可以分行的,只需要保證command的左括號和do在同一行就可以了。
  4、開關/D或/R
  含開關/D或/R的for語句是與目錄或檔案有關的命令,一般情況下很少使用。含開關/R的命令有時候被用於透過遍歷資料夾來查詢某一個檔案或資料夾,故而列舉此例。
  含開關/R的for語句舉例(資料夾遍歷):
  ===============================================
  @echo off
  setlocal enabledelayedexpansion
  FOR /R d: %%i IN (.) DO (
  set dd=%%i
  set "dd=!dd:~0,-1!"
  echo !dd!
  )
  pause
  exit
  ===============================================
  上例即可以羅列出D盤下的所有資料夾,其速度要比命令"tree d:"慢多了,不過其返回結果的實用性則遠遠超過了tree命令。
  一般情況下我們不推薦透過遍歷資料夾來查詢檔案,特別是在查詢某些程式(比如QQ.exe)的位置時。推薦透過reg命令查詢登錄檔來查詢QQ的路徑,以保證查詢效率。
  上例中也出現了幾個新面孔,如setlocal、感嘆號等。其中,感嘆號其實就是變數百分號 (%)的強化版。之所以要用!而不用%,是因為在for迴圈中,當一個變數被多次賦值時,%dd%所獲取的僅僅是dd第一次被賦予的值;要想重新整理dd的 值,就必須首先透過命令"setlocal enabledelayedexpansion"來開啟延遲變數開關,然後用!dd!來獲取dd的值。
  for語句是批處理裡面功能最強大、使用最普遍卻又最難掌握的一套命令,這也是批處理菜鳥和批處理高手最明顯的一個分水嶺,一旦掌握了這套命令,那麼你就離批處理達人不遠了!


【 六、字串處理 】

  批處理有著具有非常強大的字串處理能力,其功能絕不低於C語言裡面的字串函式集。批處理中可實現的字串處理功能有:擷取字串內容、替換字串特定欄位、合併字串、擴充字串等功能。下面對這些功能一一進行講解。
  【 1、擷取字串 】
  擷取字串可以說是字串處理功能中最常用的一個子功能了,能夠實現擷取字串中的特定位置的一個或多個字元。舉例說明其基本功能:
  =========================================
  @echo off
  set ifo=abcdefghijklmnopqrstuvwxyz0123456789
  echo 原字串(第二行為各字元的序號):
  echo %ifo%
  echo 123456789012345678901234567890123456
  echo 擷取前5個字元:
  echo %ifo:~0,5%
  echo 擷取最後5個字元:
  echo %ifo:~-5%
  echo 擷取第一個到倒數第6個字元:
  echo %ifo:~0,-5%
  echo 從第4個字元開始,擷取5個字元:
  echo %ifo:~3,5%
  echo 從倒數第14個字元開始,擷取5個字元:
  echo %ifo:~-14,5%
  pause
  =========================================
  當然,上面的例子只是將字串處理的基本功能展示出來了,還看不出字串處理具體有什麼用處。下面這個例子是對時間進行處理。
  =========================================
  @echo off
  echo 當前時間是:%time% 即 %time:~0,2%點%time:~3,2%分%time:~6,2%秒%time:~9,2%釐秒
  pause
  =========================================
  【 2、替換字串 】
  替換字串,即將某一字串中的特定字元或字串替換為給定的字串。舉例說明其功能:
  =========================================
  @echo off
  set aa=偉大的中國!我為你自豪!
  echo 替換前:%aa%
  echo 替換後:%aa:中國=中華人民共和國%
  echo aa = %aa%
  set "aa=%aa:中國=中華人民共和國%"
  echo aa = %aa%
  pause
  =========================================
  對於上面的例子有一點說明,對比兩個echo aa = %aa%可以發現,如果要修改變數aa的內容的話,就需要將修改結果“%aa:中國=中華人民共和國%”賦值給變數aa。上面的字串擷取也有著同樣的特點。
  【 3、字串合併 】
  其實,合併字串就是將兩個字串放在一起就可以了。舉例說明:
  =========================================
  @echo off
  set aa=偉大的中國!
  set bb=我為你自豪!
  echo %aa%%bb%
  echo aa=%aa%
  echo bb=%bb%
  set "aa=%aa%%bb%"
  echo aa=%aa%
  pause
  =========================================
  同樣,如果要改變變數aa的內容的話,就需要將合併結果“%aa%%bb%”賦值給變數aa。
  【 4、擴充字串 】
  “擴充”這個詞彙來自於微軟自己的翻譯,意思就是對錶示檔案路徑的字串進行特殊的處理,具體功能羅列如下:
  =========================================
  ~I - 刪除任何引號("),擴充 %I
  %~fI - 將 %I 擴充到一個完全合格的路徑名
  %~dI - 僅將 %I 擴充到一個驅動器號
  %~pI - 僅將 %I 擴充到一個路徑
  %~nI - 僅將 %I 擴充到一個檔名
  %~xI - 僅將 %I 擴充到一個副檔名
  %~sI - 擴充的路徑只含有短名
  %~aI - 將 %I 擴充到檔案的檔案屬性
  %~tI - 將 %I 擴充到檔案的日期/時間
  %~zI - 將 %I 擴充到檔案的大小
  %~$PATH:I - 查詢列在路徑環境變數的目錄,並將 %I 擴充
  到找到的第一個完全合格的名稱。如果環境變數名
  未被定義,或者沒有找到檔案,此組合鍵會擴充到
  空字串
  可以組合修飾符來得到多重結果:
  %~dpI - 僅將 %I 擴充到一個驅動器號和路徑
  %~nxI - 僅將 %I 擴充到一個檔名和副檔名
  %~fsI - 僅將 %I 擴充到一個帶有短名的完整路徑名
  %~dp$PATH:i - 查詢列在路徑環境變數的目錄,並將 %I 擴充
  到找到的第一個驅動器號和路徑。
  %~ftzaI - 將 %I 擴充到類似輸出線路的 DIR
  =========================================
  以上內容引用於for /?幫助資訊。其中的I代表變數I,不過需要說明的是,不是所有的變數都能夠進行擴充的,有兩個條件:1、該字串代表一個檔案路徑;2、變數要用%x來表示,x可取a-z A-Z 0-9共62個字元中的任意一個。舉例說明:
  =========================================
  @echo off
  echo 正在執行的這個批處理:
  echo 完全路徑:%0
  echo 去掉引號:%~0
  echo 所在分割槽:%~d0
  echo 所處路徑:%~p0
  echo 檔名:%~n0
  echo 副檔名:%~x0
  echo 檔案屬性:%~a0
  echo 修改時間:%~t0
  echo 檔案大小:%~z0
  pause
  =========================================
  其中的%0是批處理裡面的引數,代表當前執行的批處理的完全路徑。類似的還有%1-%9,分別代表傳遞來的第1-9個引數。例子如下:
  ===============================================
  @echo off
  set aa=C:\Windows\PPP\a.btx
  call :deal aaa %aa% "c c" ddd eee
  pause>nul
  exit
  :deal
  echo %%0 = %0
  echo %%1 = %1
  echo %%2 = %2
  echo %%3 = %3
  echo %%4 = %4
  echo %%5 = %5
  ===============================================
  其中,變數aa在之前是不可以擴充的,透過call命令並將aa作為引數傳遞給子函式:deal,將aa變數轉換成了變數%1,即符合%x格式,從而可以進行字串擴充。
  至於%x中x取a-z A-Z的形式,可以複習一下for語句,for語句裡面的變數就是用%x來表示的,因而可以直接進行擴充。


【 七、數值計算 】

   批處理裡面的數值計算功能較弱,只能夠進行整型計算,忽略浮點數的小數部分;同時數值計算的範圍也受限於系統位數,對於目前較為常見的32位機來說,數 值計算能處理的數值範圍為0x80000000h~0x7FFFFFFFh,即-2147483648~+2147483647。
  數值計算需要使用set命令,具體格式為“set /a expression”。其中,expression代表計算表示式,計算表示式跟C語言裡面的表示式基本上完全一致。set支援的運算子也跟C語言裡面 的一樣,只是沒有了増一減一。set支援的運算子及優先順序排序如下:
  =========================================
  () - 分組
  ! ~ - - 一元運算子(邏輯非、按位非、取負)
  * / % - 算數運算子(乘、除得商、除得餘數,即取餘)
  + - - 算數運算子(加、減)
  << >> - 邏輯移位(左移一位、右移一位)
  & - 按位“與”
  ^ - 按位“異”
  | - 按位“或”
  = *= /= %= += -= - 賦值
  &= ^= |= <<= >>=
  , - 表示式分隔符(set可一次處理多個表示式)
  =========================================
  我們知道,批處理中取變數的值是需要用%或者!的,而在set /a 中,直接用變數名稱即可取得變數的值。另外,set支援八進位制(數字字首0)、十進位制(數字無字首)和十六進位制(數字字首0x),且支援不同進位制之間的計 算,如set /a a=123+0123+0x123,計算及顯示結果為十進位制。


【 八、概念方法 】

  本節學習有關批處理的一些比較瑣碎、但又比較有價值的一些知識,運用這些知識後,才有條件更好的實現的批處理的功能,並能使批處理擺脫黑白世界而顯得更加多姿多彩。廢話少說,開講啦~
  【(一)環境變數 】
   所謂“環境變數”,實際上就是C語言裡面的“變數”的意思。批處理的變數可以分為兩類,由系統定義的系統變數和由使用者根據需要自定義的使用者變數。
  【 1、系統變數 】
  批處理的一些變數是由作業系統事先定義好的,可以適用於任何批處理,我們稱這些特殊的變數為“ 系統變數”。系統變數有很多個,包括硬體類、作業系統類、檔案路徑類、系統時間類等。要檢視所有的系統變數,請新開啟一個cmd視窗,輸入set回車即 可。對幾個比較常用的變數解釋如下:
  ComputerName 計算機名,即右鍵 我的電腦--屬性--計算機名 選項卡中的“完整的計算機名稱”
  ComSpec cmd.exe完整路徑名
  HomeDrive 系統分割槽磁碟機代號,一般都是C盤,故而HomeDrive=C:
  Path 可執行檔案預設搜尋路徑。這個東東非常重要!待會兒單獨講解…
  ProgramFiles 就是系統的Program Files的路徑啦,一般都是C:\Program Files,這就是安裝軟體時預設的安裝路徑了
  Prompt 個性化設定cmd提示符的必備武器!不過,我沒怎麼用過~
  SystemDrive 包含系統根目錄的分割槽,其實就是HomeDrive了
  SystemRoot 系統根目錄路徑,一般都是C:\WINDOWS
  Temp、Tmp 檔案、程式等可使用的臨時目錄,預設是C:\WINDOWS\Temp或Tmp。幾乎所有的程式在執行時都會在這個目錄裡面“臨時”寫入檔案。一般情況 下,程式寫入的臨時檔案都應該被該程式刪除,可惜的是,大部分的程式都很健忘,導致這個資料夾佔據的空間越來越大,自然也就使我們的系統增肥嘍。所以,我 們要把它修改到其他分割槽,並且時時的清理裡面的臨時檔案。
  UserName 當前使用者名稱,即所登陸的賬戶名
  UserProfile 當前使用者的配置目錄,一般都是C:\Documents and Settings\%UserName%。預設情況下,我們的桌面就是這個目錄下面的“桌面”資料夾;我的文件就是這個目錄下面的“My Documents”資料夾。所以啦,往桌面上或我的文件裡面放東西就是放到這個資料夾下面了,也就是放到C盤了,重灌系統時要覆蓋C盤內容的,所以桌面 上或我的文件裡面的東西當然就會Gone with the Wind了~解決方法有兩個,一是保持良好的習慣,不把重要檔案放到這兩個地方;二是,修改預設設定,將這兩個資料夾都移到其他分割槽。
  WinDir 作業系統路徑,其實就是SystemRoot了
  【 2、使用者變數 】
  編寫批處理程式時,使用者根據需要自己定義的變數稱之為使用者變數。使用者變數類似於C語言裡面的變數,僅僅在定義該變數的程式中有效。
  使用者變數由set命令定義,這是批處理中非常非常重要的一個操作,從而使set命令成為批處理裡面使用頻率最高的幾個命令之一。關於set命令的使用,參考set /?,本教程也會在後面對其進行講解。
  【 3、變數引用 】
  前面的幾節課裡面,我們已經看到了如何引用變數,即直接用變數名操作變數,透過"%"或"!" 來獲取變數的值。其中,只有在for語句裡面重複對同一變數多次賦值時才需要使用"!",並且在使用"!"呼叫變數時,要首先“啟用延遲環境變數擴充”, 啟動命令為:SetLocal EnableDelayedExpansion。另外需要說明的是,“啟用延遲環境變數擴充”後,所有的"!"都將被視為“取變數值”的特殊符號,即使 用"^!"也不能輸出符號"!"。若要輸出"!",則需要“停用延遲環境變數擴充”,命令為:SetLocal DisableDelayedExpansion
  【(二)引數 】
  跟C語言類似,在呼叫函式或其他批處理時可能需要傳遞引數。批處理的引數傳遞分為直接和間接兩種傳遞引數的方法。
  【 1、直接傳遞 】
  直接傳遞引數,即在使用call命令時,不使用任何引數,在子函式或子批處理裡面直接對主函式(也稱父批處理)裡面的變數進行修改。這跟組合語言裡面的引數傳遞方式類似。
  直接傳遞引數舉例:
  ===============================================
  @echo off
  setlocal enabledelayedexpansion
  set var=aCdehiM,?mnrstW y
  echo %var%
  call :deal
  setlocal disabledelayedexpansion
  set var=%var:?=!%
  echo %var%
  pause>nul
  exit
  :deal
  set tm=!var!
  set var=
  for %%i in (6,3,11,11,16,15,1,4,11,5,12,13,9,0,12,7,15,14,5,10,2,16,18,8) do (
  set var=!var!!tm:~%%i,1!
  )
  goto :eof
  ===============================================
  可以發現,當我們把變數var作為引數賦予子函式:deal後,子函式對var的值進行了修改;當子函式返回後,主函式里面的var的值就已經是子函式里面var被修改後的值了。
  該例子中,使用了本節課前面講到的setlocal enabledelayedexpansion和setlocal disabledelayedexpansion,前者保證了var在for迴圈裡面能夠根據我們的意願進行處理,後者保證了能夠正確輸出符號"!"。另 外例子中還使用了命令set,利用set對字串進行了處理。還有一個地方使用了語句goto :eof,該語句相當於C語言裡面的return或組合語言裡面的RET,即子程式返回命令。需要說明的是,當子函式本身就在批處理檔案的末尾的話,我們 是可以省略這句話的,比如將此例的goto :eof刪除是不會產生任何影響的。
  【 2、間接傳遞 】
  間接傳遞引數,即在使用call命令時,在其後面新增引數,形如call {[:label][ChildBatch]} Parameter1 Parameter2 ... ParameterN。這跟C語言裡面傳遞引數的格式類似。不同於C語言,批處理中的子函式不需要定義形參,更不需要指定引數的個數。傳遞過來的引數,在 子函式或子批處理裡面是以%1~%9的形式表示的,即%1~%9分別表示傳遞過來的第1~9個引數。
  ===============================================
  @echo off
  call :deal aaa bbb "c c" ddd eee
  pause>nul
  exit
  :deal
  echo %%0 = %0
  echo %%1 = %1
  echo %%2 = %2
  echo %%3 = %3
  echo %%4 = %4
  echo %%5 = %5
  ===============================================
  透過這個例子就可以清晰的看到%n參數列示法的用法。引數列表中包含空格的依舊要用雙引號(")引起來;另外,也可以看到,%0已經變成了子函式的標號了,而不是父批處理的檔名全稱。
  【 3、區別 】
  這兩種引數傳遞方法本質上是沒有區別的,形式上,直接傳遞直接對原變數進行操作,丟失了原變數 的值;間接傳遞則透過%n對原變數進行了簡單的備份,並且通用性更強,即不限定原變數的名稱。另外,使用%n還有一個非常大的好處,就是可以透過%~*i 來加強處理變數的能力。關於%~*i,詳細內容參見for /?。
  針對二者的差別,可以根據情況決定使用哪種傳遞方式:
  --1、作為引數的變數名固定、且在子函式中不需要對其進行備份的情況下,使用直接傳遞法;
  --2、若將子函式作為一個通用的程式模組,以適應於對不同變數的處理,或者作為引數的變數不需要備份時,使用間接傳遞法。
  具體使用哪種方法,還需根據實際情況或使用習慣進行選擇。
  【(三)返回值 】
  有些命令在執行之後將會返回一定的錯誤值(errorlevel),可以透過errorlevel的值判斷命令執行的狀況。這點類似於C語言裡面的exit(num),num就是錯誤程式碼。
  獲取返回值errorlevel的方法就是,在執行命令後,立馬呼叫返回值errorlevel,如echo %errorlevel%或者if %errorlevel%==1等命令。
  errorlevel舉例:
  ===============================================
  @echo off
  reg add HKCU /v try /f>nul
  reg delete HKCU /v try /f
  if errorlevel 0 (echo 刪除成功!) else (echo 刪除失敗!)
  reg delete HKCU /v try /f
  if %errorlevel%==0 (echo 刪除成功!) else (echo 刪除失敗!)
  pause>nul
  ===============================================
  上面例子中,由於第一成功的刪除了登錄檔,導致第二次因為找不到登錄檔而宣告失敗。同時我們也 看到了errorlevel的使用方法,即if errorlevel 0和if %errorlevel%==0是一樣的。也許你注意到了,裡面還有個笑臉呢~O(∩_∩)O哈哈~這就是ASCII碼啦,後面跟你講啊…
  一般情況下,程式或命令成功執行時,返回的errorlevel是0,錯誤時返回1或更高的值。當然,有些命令是沒有返回值的,這點需要注意。
  嗯,有沒有想起前面有個類似的東西啊?對了,那就是||和&&了,這兩個符號就是根據errorlevel的值來進行邏輯判斷的~
  【(四)使用者互動 】
  批處理,黑框白字是它最著名的特徵。雖然當初DOS為人們使用計算機做出了莫大的貢獻,但在 Windows盛行的今天,人們已經疏遠並且懼怕那個黑色的視窗了。微軟為了讓先天有著批次處理“體力活”能力的DOS避免“冷酷”,便於接近,特意提供 了幾個小命令,加強批處理的使用者互動功能。
  【 1、視窗 】
  首先我們要DIY它的視窗。使用命令:color、mode、msg。
  --1、設定視窗背景色和字型顏色by color。詳細內容參見color /?。
  --2、設定視窗大小by "MODE CON [COLS=c] [LINES=n]",cols即寬度,lines即高度。
  --3、GUI互動視窗by msg。詳細內容參見msg /?。
  視窗DIY舉例:
  ===============================================
  @echo off
  set a=10
  set b=0
  :tex
  set /a a+=3
  set /a b+=1
  mode con cols=%a% lines=%b%
  if %a% lss 60 goto :tex
  echo O(∩_∩)O 聖誕快樂 O(∩_∩)O
  set a=15,a6,2e,d0,34,8b,4f,9d,5e
  for %%i in (%a%) do (
  ping -n 2 127.1>nul
  color %%i
  )
  for %%i in (%a%,%a%) do (
  ping -n 1 127.1>nul
  color %%i
  )
  >>ms.txt echo */. . . * .
  >>ms.txt echo .\* . [] * __
  >>ms.txt echo */ . ./\~~~~~~~~~~~~'\. ^|◆
  >>ms.txt echo \* ,/,..,\,...........,\.◆
  >>ms.txt echo ^|^| ..▎# ▎田 田 ▎ ^| ▎◆
  >>ms.txt echo ^|^| ^&^&▎ ▎ ▎'^|'▎ o
  >>ms.txt echo ^|^| ##■■■■■■■■■■〓
  msg %username% /w /time:3600   del ms.txt
  pause
  ===============================================
  【 2、聲音 】
  呵呵,是不是注意到了批處理沒有聲音吶?閒話不說,直接做實驗吧 ^_^
  ===============================================
  @echo off
  echo 做好準備,響了啊!!
  pause
  cls
  echo
  echo 怎麼樣?呵呵,刺激吧~
  pause
  cls
  mshta vbscript.:createobject("sapi.spvoice").speak("Merry Christmas and Happy New Year!")(window.close)
  pause
  ===============================================
  speak好像不能講中文吶~
  ■●●●●
  此處錯誤,如果tts安裝了中文引擎是可以講中文的。
  此外,這個就是呼叫vbs的方法:vbscript.:createobject("sapi.spvoice").speak("Merry Christmas and Happy New Year!")
  ●●●●■
  【 3、控制 】
  在執行批處理的過程中,我們如何幹預批處理呢?呵呵,直接點叉叉就可以結束它了!嗯,不錯,不過,太野蠻了~
  --1、暫停批處理:直接按鍵盤上的Pause鍵嘍
  --2、終止批處理:組合鍵Ctrl+C。不過,有時候它好像響應的不太積極啊…
  【(五)ASCII碼 】
  前面的例子中,我們已經使用過一次ASCII碼了,也就是那個笑臉。ASCII碼是圖形化的符號,可以用來點綴我們的批處理的。
  在cmd視窗中我們可以透過任意一個字元的ASCII碼來輸入該字元,比如Ctrl+G、 Ctrl+N等,字母a-z對應ASCII碼的1-26。對於ASCII碼大於26的字元,可以透過這個方法來輸入:按住Alt鍵不松,透過小鍵盤輸入 ASCII碼的十進位制值,鬆開Alt鍵即可。 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/9606200/viewspace-745694/,如需轉載,請註明出處,否則將追究法律責任。

相關文章