Windows批處理bat基礎知識總結
編者按:這兩天在寫bat指令碼,這是一個痛苦的週末,來個bat的基礎知識,留著以後慢慢學。
預定義的變數
下面是些已經被底層定義好可以直接使用的變數:不會出現在 SET 顯示的變數列表中
%CD% – 擴充套件到當前目錄字串。
%DATE% – 用跟 DATE 命令同樣的格式擴充套件到當前日期。
%TIME% – 用跟 TIME 命令同樣的格式擴充套件到當前時間。
%RANDOM% – 擴充套件到 0 和 32767 之間的任意十進位制數字。
%ERRORLEVEL% – 擴充套件到當前 ERRORLEVEL 數值。
%CMDEXTVERSION% – 擴充套件到當前命令處理器副檔名版本號。
%CMDCMDLINE%
%0 bat的完整路徑名如”C:\Windows\system32\xxx.bat”
%1 bat引數1依次類推%2引數2…
%path% – 當前的環境變數。以分號隔開的路徑列表,路徑可包含空格,可以以’\’結尾, 可以以雙引號包圍之。
引數%0具有特殊的功能,可以呼叫批處理自身,以達到批處理本身迴圈的目的,也可以複製檔案自身等等。
例:最簡單的複製檔案自身的方法
copy %0 d:\wind.bat
擴充套件變數
@ 與%i相關的變數(bat引數或者for迴圈的%i)
假設檔案為C:\Documents and Settings\jinsun\桌面\ParseSinglePkgs.bat
%0
%~dp0 C:\Documents and Settings\jinsun\桌面\
%cd% C:\Documents and Settings\jinsun\桌面
%~nx0 ParseSinglePkgs.bat
%~n0 ParseSinglePkgs
%~x0 .bat
@ 與%VAR%相關的變數
%VAR:str1=str2% 會將VAR中的str1替換為str2(str2如果為空則可以達到刪除的效果,str1前可以加*,變數%ABC:*B=%是C)
%VAR:~0,-2%
%VAR:~2% 會提取VAR 變數的除前兩個的所有字元
%VAR:~-2% 會提取VAR 變數的最後兩個
%VAR:~2,5% 提取從第2個字元開始的5個字元
在bat檔案中,多個命令寫在一行或括號內,如果使用行內或括號內定義或修改的變數,需要啟用延遲變數擴充,用歎號引用變數。
bat檔案中用 setlocal enabledelayedexpansion 啟用延遲變數擴充,命令提示符視窗啟用延遲變數擴充,用 cmd /v:on
ren命令中的檔名最好加引號,防止檔名包含空格等特殊字元造成的錯誤。
cd /d %~dp0
批處理檔案中的一條語句
意思是 更改當前目錄為批處理本身的目錄
比如你有個批處理a.bat在D:\qq資料夾下
a.bat內容為
cd /d %~dp0
在這裡
cd /d 表示直接轉換到後面的路徑,否則如果切換碟符,就需要再輸入碟符才能切換路徑
cd /d %~dp0的意思就是cd /d d:\qq
%0代表批處理本身 d:\qq\a.bat
~dp是變數擴充
d既是擴充到分割槽號 d:
p就是擴充到路徑 \qq
dp就是擴充到分割槽號路徑 d:\qq
%0代指批處理檔案自身
%~d0 是指批處理所在的碟符
%~dp0 是碟符加路徑
cd %~dp0 就是進入批處理所在目錄了
%cd%
%cd%代表當前執行批處理檔案的路徑(當前路徑)
echo %cd%
%CD% 當前檔案目錄,不顯示檔名,切通過其找到其他檔案
%0 當前檔案本身,包含完整路徑名和檔名
如 “C:\Windows\system32\xxx.bat”,是一個路徑字串,有引號
*.* 代表所有檔案
>和>>它們的作用都是改變各種提示資訊的輸出方向,把提示資訊輸出到指定的地方去——各種提示資訊預設是輸出到螢幕上去的。
單個的>表示以覆蓋方式重定向提示資訊,也就是說如果目的地原來有內容,將把原來的內容清除掉,用新內容填充;
>>表示以追加的方式重定向提示資訊,也就是說,如果目的地原來有內容,原有的內容將保持不變,在原有內容之後追加新內容。
例如:假設d:\test.txt中的內容是:I Love batch。那麼,在cmd視窗中,分別使用如下兩條語句:echo me,too>d:\test.txt和echo me,too>>d:\test.txt,將會發現,使用第一條語句之後,test.txt中只有一行內容:me,too,而使用第二條語句之後,test.txt中將有兩行內容,分別是I Love batch和me,too。
例如:tree /?>help.txt,這條命令語句就把 tree 命令的幫助資訊重定向到了help.txt檔案中,
help>nul 就把 help 命令的提示資訊重定向到了空裝置中去(nul表示空裝置)。
| 命令管道符
格式:第一條命令 | 第二條命令 [| 第三條命令…]
將第一條命令的結果作為第二條命令的引數來使用,記得在unix中這種方式很常見。
例如:
dir c:\|find “txt”
以上命令是:查詢C:\所有,並發現TXT字串。
md
如果要建立的資料夾帶有空格或&,需要用引號把資料夾名括起來,例如:md “test abc”、md “abc&xyz”。
如果不使用引號,又會帶來什麼後果呢?
1、如果資料夾名帶空格,那麼,md test abc 語句會在當前目錄下建立test和abc這兩個資料夾;利用這個特點,如果要建立abc def xyz這三個資料夾,直接使用 md abc def xyz 就行了,而無需連寫三條md語句。
當然,md abc;def;xyz或者md abc,def,xyz 這樣的寫法也是可以的。
2、如果資料夾名中含有&,那麼,md abc&xyz 會建立abc這個資料夾,並提示說:’xyz’不是內部或外部命令,也不是可執行的程式或批處理檔案,這是因為,&是複合語句的連線符號,它把前後兩部分視為兩條子語句了。
忠告:如果資料夾名含有特殊符號,請不要忘記使用雙引號!
md建立中級目錄。也就是說,md a\b\c這樣的命令,可以在當前目錄下建立資料夾a,然後,在a下建立資料夾b,b之下再建立資料夾c
echo on/off
on 和 off 都是echo 的關鍵字,所謂關鍵字就是系統規定、有特殊用途的字元。
echo on 是打開回顯,echo off 是關閉回顯。
系統預設是echo on,所以每次為了關閉回顯,都會在程式碼的行首加上echo off,加以關閉。
不關閉回顯,連執行的命令符都會顯示出來,所以一般會關閉。
前面加上@又是為什麼?
echo off只能關閉 echo off後面的程式碼的回顯,但不能關閉自身的回顯。所以需要加上@關閉自身。
echo.
echo 後加一點表示換行,真奇葩的設計。
findstr預設是區分大小寫的(跟find命令一樣)
findstr /vm “^teststring” *.txt
findstr /v /m “teststring” *.txt
/i 不區分大小寫 (/ignore)
/V 只打印不包含匹配的行。
/M 如果檔案含有匹配項,只打印其檔名。
啟動一個程式
call與start區別
start upload.bat
不會等upload.bat執行完再執行下一條, 如此可實現同時執行多條命令.
call upload.bat
call 命令 是要等呼叫的程式結束以後才執行下面的命令.
特殊符號
&:第一條命令 & 第二條命令 [& 第三條命令…]
用這種方法可以同時執行多條命令,而不管命令是否執行成功。
&&:第一條命令 && 第二條命令 [&& 第三條命令…]
當碰到執行出錯的命令後將不執行後面的命令,如果一直沒有出錯則一直執行完所有命令。
||:第一條命令 || 第二條命令 [|| 第三條命令…]
當碰到執行正確的命令後將不執行後面的命令,如果沒有出現正確的命令則一直執行完所有命令;
Sql程式碼
- @echo off
- for /? > for.txt
- set /? > set.txt
- shift /? >shift.txt
- exit
執行後在當前路徑下就生成for.txt、set.txt和shift.txt三個檔案,裡面分別記錄了for命令、set命令和shift命令的幫助資訊。
1.Echo 命令
打開回顯或關閉請求回顯功能,或顯示訊息。
如果沒有任何引數,echo 命令將顯示當前回顯設定。
語法
echo [{on|off}] [message]
Sample:
@echo off / echo hello world
在實際應用中我們會把這條命令和重定向符號(也稱為管道符號,一般用> >> ^)結合來實現輸入一些命令到特定格式的檔案中.這將在以後的例子中體現出來。
[email protected] 命令
表示不顯示@後面的命令
在入侵過程中(例如使用批處理來格式化敵人的硬碟)自然不能讓對方看到你使用的命令啦。
Sample:@echo off
@echo Now initializing the program,please wait a minite…
@format X: /q/u/autoset (format 這個命令是不可以使用/y這個引數的,可喜的是微軟留了個autoset這個引數給我們,效果和/y是一樣的。)
3.Goto 命令
指定跳轉到標籤,找到標籤後,程式將處理從下一行開始的命令。
語法:goto label (label是引數,指定所要轉向的批處理程式中的行。)
Sample:
Ruby程式碼
- 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命令就是根據這個:來尋找下一步跳到到那裡。最好有一些說明這樣你別人看起來才會理解你的意圖啊。
4.Rem 命令
註釋命令,在C語言中相當與/*——–*/,它並不會被執行,只是起一個註釋的作用,便於別人閱讀和你自己日後修改。
Rem Message
Sample:
@Rem Here is the description.
註釋可以使用Rem,也可以使用雙冒號即::
5.Pause 命令
執行 Pause 命令時,將顯示下面的訊息:
Press any key to continue . . .
Ruby程式碼
- @echo off
- :begin
- copy a:*.* d:\back
- echo Please put a new disk into driver A
- pause
- goto begin
在這個例子中,驅動器 A 中磁碟上的所有檔案均複製到d:\back中。顯示的註釋提示您將另一張磁碟放入驅動器 A 時,pause 命令會使程式掛起,以便您更換磁碟,然後按任意鍵繼續處理。
6.Call 命令
call命令用來從一個批處理指令碼中呼叫另一個批處理指令碼
如果在指令碼或批處理檔案外使用 Call,它將不會在命令列起作用。
語法
call [[Drive:][Path] FileName [BatchParameters]] [:label [arguments]]
引數
[Drive:}[Path] FileName
指定要呼叫的批處理程式的位置和名稱。filename 引數必須具有 .bat 或 .cmd 副檔名。
Ruby程式碼
- call mvn clean
7.start 命令
呼叫外部程式,所有的DOS命令和命令列程式都可以由start命令來呼叫。
入侵常用引數:
MIN 開始時視窗最小化
SEPARATE 在分開的空間內開始 16 位 Windows 程式
HIGH 在 HIGH 優先順序類別開始應用程式
REALTIME 在 REALTIME 優先順序類別開始應用程式
WAIT 啟動應用程式並等候它結束
parameters 這些為傳送到命令/程式的引數
執行的應用程式是 32-位 GUI 應用程式時,CMD.EXE 不等應用程式終止就返回命令提示。如果在命令指令碼內執行,該新行為則不會發生。
8.choice 命令
choice 此命令可以讓使用者輸入一個字元,從而執行不同的命令。使用時應該加/c:引數,c:後應寫提示可輸入的字元,之間無空格。它的返回碼為1234……
如: choice /c:dme defrag,mem,end
將顯示
defrag,mem,end[D,M,E]?
Ruby程式碼
- @echo off
- choice /c:dme defrag,mem,end
- if errorlevel 3 goto defrag (應先判斷數值最高的錯誤碼)
- if errorlevel 2 goto mem
- if errotlevel 1 goto end
- :defrag
- c:\dos\defrag
- goto end
- :mem
- mem
- goto end
- :end
- echo good bye
此檔案執行後,將顯示 defrag,mem,end[D,M,E]? 使用者可選擇d m e ,然後if語句將作出判斷,d表示執行標號為defrag的程式段,m表示執行標號為mem的程式段,e表示執行標號為end的程式段,每個程式段最後都以goto end將程式跳到end標號處,然後程式將顯示good bye,檔案結束。
9.If 命令
if 表示將判斷是否符合規定的條件,從而決定執行不同的命令。 有三種格式:
1、if “引數” == “字串” 待執行的命令
檢測字串
(注意,用if檢測字串是否相等的時候,後面用的不是“=”,而是“==”)
引數如果等於指定的字串,則條件成立,執行命令,否則執行下一句。(注意是兩個等號)
如if “%1″==”a” format a:
if {%1}=={} goto noparms
if {%2}=={} goto noparms
檢測數值:(注意,批處理中大於符號不能用:“>”,而用”gtr”,其它的也類似)
比較運算子一覽:
EQU – 等於
NEQ – 不等於
LSS – 小於
LEQ – 小於或等於
GTR – 大於
GEQ – 大於或等於
Sql程式碼
- @echo off
- set /a num1=20
- set /a num2=15
- if %num1% gtr %num2% echo %num1%大於%num2%
- if %num1% EQU %num2% echo %num1%等於%num2%
- if %num1% LSS %num2% echo %num1%小於%num2%
- pause>nul
、if exist 檔名 待執行的命令
如果有指定的檔案,則條件成立,執行命令,否則執行下一句。
如if exist config.sys edit config.sys
3、if errorlevel / if not errorlevel 數字 待執行的命令
如果返回碼等於指定的數字,則條件成立,執行命令,否則執行下一句。
說明:環境變數errorlevel的初始值為0,當一些命令執行不成功,就會返回一個數值,如:1 ,2 等
如if errorlevel 2 goto x2
DOS程式執行時都會返回一個數字給DOS,稱為錯誤碼errorlevel或稱返回碼,常見的返回碼為0、1。
IF [NOT] ERRORLEVEL number do command
IF [NOT] string1==string2 do command
IF [NOT] EXIST filename do command
10.for 命令
for 命令是一個比較複雜的命令,主要用於引數在指定的範圍內迴圈執行命令。
在批處理檔案中使用 FOR 命令時,指定變數請使用 %%variable
在批處理檔案中使用 FOR 命令時,指定變數請使用 %%variable而不要用 %variable。變數名稱是區分大小寫的,所以 %i 不同於 %I
for /f %%i in (a.txt) do echo %%i
//這個會顯示a.txt裡面的內容,因為/f的作用,會讀出a.txt中的內容。
for %%i in (a.txt) do echo %%i
//而這個只會顯示a.txt這個名字,並不會讀取其中的內容。
for %%a in (c:\*.*) do echo %%a
::顯示C盤根目錄下所有非隱藏、非系統屬性檔案
::只顯示檔案,不顯示資料夾
一、/d
(只搜尋目錄,不搜尋檔案)
格式:FOR /D %variable IN (set) DO command [command-parameters]
for /d %%i in (c:/*) do echo %%i –顯示c盤根目錄下的所有目錄
for /d %%i in (???) do echo %%i –顯示當前目錄下名字只有1-3個字母的目錄(注意是目錄)
二、/R
(只搜尋檔案,不搜尋目錄)
(搜尋指定路徑及所有子目錄中與set相符合的所有檔案)
格式:FOR /R [[drive:]path] %variable IN (set) DO command [command-parameters]
for /r c:/ %%i in (boot.ini) do echo %%i
–枚舉了c盤所有目錄,找到含有boot.ini的路徑並顯示
for /r d:/backup %%i in (1) do echo %%i
–列舉d/backup目錄,現在當前路徑和當前路徑下所有資料夾,不過後面帶了個1
d:\backup\1
for /r c:/ %%i in (boot.ini) do if exist %%i echo %%i
–很好的搜尋命令,列舉boot.ini存在的目錄
三、/L
(以增量形式從開始到結束的一個數字序列。可以使用負的 Step)
格式:FOR /L %variable IN (start,step,end) DO command [command-parameters]
該集表示以增量形式從開始到結束的一個數字序列。可以使用負的 Step
示例:
for /l %%i in (1,1,5) do @echo %%i –輸出1 2 3 4 5
for /l %%i in (1,2,10) do @echo %%i –輸出1,3,5,7,9
for /l %%i in (100,-20,1) do @echo %%i –輸出100,80,60,40,20
for /l %%i in (1,1,5) do start cmd –開啟5個CMD視窗
for /l %%i in (1,1,5) do md %%i –建立從1~5共5個資料夾
for /l %%i in (1,1,5) do rd /q %%i –刪除從1~5共5個資料夾
setlocal 與 變數延遲
例1:
@echo off
set a=4
set a=5 & echo %a%
pause
結果:4
解說:為什麼是4而不是5呢?在echo之前明明已經把變數a的值改成5了?
(set a=5
echo %a%
::這種情況a直接是5
)
讓我們先了解一下批處理執行命令的機制:
批處理讀取命令時是按行讀取的(另外例如for命令等,其後用一對圓括號閉合的所有語句也當作一行),在處理之前要完成必要的預處理工作,這其中就包括對該行命令中的變數賦值。我們現在分析一下例1,批處理
在執行到這句“set a=5 & echo %a%”之前,先把這一句整句讀取並做了預處理——對變數a賦了值,那麼%a%當然就是4了!(沒有為什麼,批處理就是這樣做的。)
而為了能夠感知環境變數的動態變化,批處理設計了變數延遲。簡單來說,在讀取了一條完整的語句之後,不立即對該行的變數賦值,而會在某個單條語句執行之前再進行賦值,也就是說“延遲”了對變數的賦值。
那麼如何開啟變數延遲呢?變數延遲又需要注意什麼呢?舉個例子說明一下:
例2:
@echo off
setlocal enabledelayedexpansion
set a=4
set a=5 & echo !a!
pause
結果:5
解說:啟動了變數延遲,得到了正確答案。變數延遲的啟動語句是“setlocal enabledelayedexpansion”,並且變數要用一對歎號“!!”括起來(注意要用英文的歎號),否則就沒有變數延遲的效果。
分析一下例2,首先“setlocal enabledelayedexpansion”開啟變數延遲,然後“set a=4”先給變數a賦值為4,“set a=5 & echo !a!”這句是給變數a賦值為5並輸出(由於啟動了變數延遲,所以批處理能夠感知到動態變化,即不是先給該行變數賦值,而是在執行過程中給變數賦值,因此此時a的值就是5了)。
再舉一個例子鞏固一下。
例3:
@echo off
setlocal enabledelayedexpansion
for /l %%i in (1,1,5) do (
set a=%%i
echo !a!
)
pause
結果:
1
2
3
4
5
(若不加延遲變數,則會輸出幾個!a!字元)
解說:本例開啟了變數延遲並用“!!”將變數擴起來,因此得到我們預期的結果。如果不用變數延遲會出現什
麼結果呢?結果是這樣的:
ECHO 處於關閉狀態。
ECHO 處於關閉狀態。
ECHO 處於關閉狀態。
ECHO 處於關閉狀態。
ECHO 處於關閉狀態。
即沒有感知到for語句中的動態變化。
文/uule
原文出處——http://uule.iteye.com/blog/2076859