windows腳本-CMD和Batch
一、DOS,CMD和batch
DOS是磁盤操作系統(tǒng)(英文:Disk Operating System)的縮寫,是個人計算機上的一類操作系統(tǒng)。從1981年直到1995年的15年間,DOS在IBM PC兼容機市場中占有舉足輕重的地位【1】。
batch是DOS系統(tǒng)下的腳本,這些腳本是純文本文檔,以.bat為結(jié)尾,可以用任何文本編輯器來進行編輯。它的特點是文件的每一行都是當作命令來運行。
CMD是用來運行batch的程序,在windows上是一個32位的命令行程序,基于windows操作系統(tǒng)的命令解釋程序。
二、CMD的常用命令和batch的常用示例
雖然今天的操作系統(tǒng)已經(jīng)發(fā)展的很好了,但是基于DOS的CMD還是有很大的用途的如在安裝java后驗證版本,運行java程序,注冊表重新注冊,設(shè)定時間日期,初始化網(wǎng)絡(luò)連接等。要對CMD進行學(xué)習(xí),先了解幾個常用的CMD的命令,在windows下面試試效果。
(1)幫助命令 /?
這個比較常用單獨說明,遇到不懂的看幫助文檔就可以。
命令是:命令+/? 如cd /?會跳出如下界面
(2)其它命令
netstat -a:查看所有的端口
tasklist:查看所有的進程
dir(directory):列出當前目錄下的文件以及文件夾
md (make directory):創(chuàng)建目錄
rd (remove directory): 刪除目錄(帶內(nèi)容的文件或者文件夾不能直接刪除,必須先刪除里面,再刪除外面)。如果要刪除非空目錄,可以使用命令
rd /s xxxdir或者rd /s /q xxxdir
cd (change directory) :改變指定目錄(進入指定目錄)
cd..:退回到上一級目錄
cd\:退回到根目錄
del (delete): 刪除文件,刪除一堆后綴名一樣的文件*.txt
exit: 退出dos命令行
cls : (clear screen)清屏
(3)batch文件
batch文件就是一些CMD的命令組合
1. 同時運行多個程序
打開電腦時需要同時運行多個程序,比如打開QQ,瀏覽器,等
@echo off
echo Starting QQ...
::路徑改成自己相應(yīng)的
start "" "D:\Program Files\QQ\qq.exe"
echo Starting matlab...
start "" "D:\Program Files\MATLAB\R2013a\bing\matlab.exe"
echo Starting Google Talk...
start "" "D:\Program Files\Gtalk\googletalk.exe"
2.批量重命名文件
現(xiàn)有一堆照片,命名格式為0001.jpg,0002.jpg,0003.jpg,…,00020.jpg,……要求在所有文件名前加上A_
@echo off
rem 啟用"延緩環(huán)境變量擴充"
setlocal EnableDelayedExpansion
set a=1
rem 循環(huán)當前目錄下所有圖片的文件名,支持帶空格的名稱
for /f "delims=" %%i in ('dir /b *.jpg') do (
rem 如果沒有相同的文件名,則繼續(xù)
if not "%%~ni"=="%~n0" (
if !a! LSS 10 (ren "%%i" "A_000!a!.jpg") else ren "%%i" "A_!a!.jpg"
rem 設(shè)置數(shù)值型變量a=a+1
set /a a+=1
)
)
echo 批量重命名完成!
pause
三、batch中常用的一些符號和命令
batch的命令很多但是常用的沒多少,所以本文首先介紹batch文件中常見的一些符合和命令,然后介紹bat文件的程序流程控制
1. 常用的一些符合和命令
1.1 @:表示不顯示@后面的命令。常用的命令有@echo off,其中echo off表示可以關(guān)閉掉整個批處理命令的回顯,但不能關(guān)掉ECHO OFF這個命令,現(xiàn)在我們在ECHO OFF這個命令前加個@,就可以關(guān)掉ECHO OFF這個命令。
這條語句的用處是能讓我們更加清楚看到命令的結(jié)果,比如在cmd上顯示1-5,下面分別展示有@echo off和沒有的區(qū)別
@echo off
echo %1
::Show 1 to 5
for /l %%i in (1,1,5) do (
set a=%%i
echo !a!
)
pause
沒有@echo off
1.2 %
百分號用在不同的場合,有不同的含義:
① 當百分號成對出現(xiàn),并且其間包含非特殊字符時,一般做變量引用處理,比如:%var%、%str%。這樣引用的目的是,如果不添加%那么解釋器就把這個本來是變量的值當成了字符了。
把以下代碼保存為批處理文件,運行后觀察屏幕顯示結(jié)果:
@echo off
set str=abd
echo var str's value :str
echo var str's value :%str%
pause
在屏幕上將顯示這樣的結(jié)果:
另外,百分號作為變量引用還有一種特殊形式,那就是對形式參數(shù)的引用,此時,單個百分號后面緊跟0~9這10個數(shù)字,如%0、%1,其中,%0為腳本本身的名稱,%1至%9為第二至九個參數(shù)...最多支持%0~%9,%10以后就是變量引用了,即%15為%1的值接上5。
請看演示代碼:
@echo off
if defined str goto next
set str=
set /p str=請把文件拉到本窗口后回車:
call "%~0" %str%
pause
exit
:next
cls
echo 本批處理文件完整路徑為:"%~0"
echo 拖到本窗口的文件完整路徑為:"%~1"
goto :eof
1.3 :、::
① :以:打頭的單個的:表示該行是一個標簽,它之后的內(nèi)容是一個標簽段,如:test,則表示:test之下的內(nèi)容是標簽段,而test是這個標簽段的名,可以用 goto test 、goto :test 跳轉(zhuǎn)到該標簽段或用 call :test 調(diào)用該子過程;
②:: 而連續(xù)兩個冒號打頭表示該行內(nèi)容為注釋內(nèi)容,實際上,:: 是個無效的標簽名,:加上空格同樣可以起到注釋的作用,此時,::的功能和注釋命令rem相同;但是,rem 注釋語句中的某些命令符號如重定向符號和管道符號還是會執(zhí)行,而如果用::來注釋的時候,與::同處一行的所有命令或符號直接被命令解釋器忽略掉,無形中提高了注釋的兼容性和整個程序的執(zhí)行效率,并且在眾多的命令語句中更顯得醒目,所以,注釋語句推薦使用::的格式。
1.4 ~
① 用在 set /a 語句中時,它是一元運算符號,表示將操作數(shù)字按位取反,例如,set /a num=~1的執(zhí)行結(jié)果是-2,set /a num=~0的結(jié)果是-1
② 用在for語句中,表示增強for的功能,能夠提取到更多的信息。例如:在批處理文件的for語句中:%%~i表示去掉第一對外側(cè)引號,%%~zi表示獲取文件的大小(以字節(jié)為單位),%%~ni表示獲取文件名,%%~xi表示獲取擴展名(帶點號)……它們可以組合使用,如%%~nxi表示獲取文件名和后綴名。
1.5、>、>>
一般而言,>表示用新內(nèi)容覆蓋原文件內(nèi)容,>>表示向原文件追加內(nèi)容,此時,它們以重定向符號的身份出現(xiàn);
1.6、|
一般而言,它以管道符號的身份出現(xiàn),表示把在它之前的命令或語句的執(zhí)行結(jié)果作為在它之后的命令或語句的處理對象,簡而言之,就是把它之前的輸出作為它之后的輸入,例如:echo abcd|findstr "b",表示把echo abcd的執(zhí)行結(jié)果,作為findstr "b" 的執(zhí)行對象,也就是在字符串a(chǎn)bcd中查找b字符;如果test.txt中有abcd字符串,則該語句與 findstr "b" test.txt 具有同樣的效果;
1.7、^
一般而言,^以轉(zhuǎn)義字符的身份出現(xiàn)。因為在 cmd環(huán)境中,有些字符具備特殊功能,如>、>>表示重定向,|表示管道,&、&&、||表示語句連接……它們都有特定的功能,如果需要把它們作為字符輸出的話,echo >、echo | ……之類的寫法就會出錯——cmd解釋器會把它們作為具有特殊功能的字符對待,而不會作為普通字符處理,這個時候,就需要對這些特殊字符做轉(zhuǎn)義處理:在每個特殊字符前加上轉(zhuǎn)義字符^,因此,要輸出這些特殊字符,就需要用 echo ^>、echo ^|、echo ^|^|、echo ^^……之類的格式來處理;
1.8、&
一般而言,&表示兩條命令或語句同時執(zhí)行的意思。如 echo a&echo b,將在屏幕上同時顯示a和b字符。當幾條語句含義近似或作用相同且沒有先后的順序之別時,啟用&符號連接這些語句將會增加程序的可讀性;
1.9、&&、||
這是一對含義截然相反的命令符,&&表示如果它之前的語句成功執(zhí)行,將執(zhí)行它之后的語句,而||則表示如果它之前的語句執(zhí)行失敗,將執(zhí)行它之后的語句;在某些場合,它們能替代 if……else…… 語句;例如:
@echo off
md test&&echo 成功創(chuàng)建文件夾test||echo 創(chuàng)建文件夾test失敗
pause
效果等同于如下代碼:
@echo off
md test
if "%errorlevel%"=="0" (echo 成功創(chuàng)建文件夾test) else echo 創(chuàng)建文件夾test失敗
pause
1.10、+、-、*、/
在 set /a 語句中,這些符號的含義分別為:加、減、乘、除。例如:set /a num=1+2-3*4/5。需要注意的是,這些運算符號遵循數(shù)學(xué)運算中的優(yōu)先級順序:先乘除后加減,有括號的先算括號,并且,直接忽略小數(shù)點,因此,剛才那個算式的結(jié)果是1而不是0或0.6。
另外,有可能會在代碼中看到這樣的寫法:set /a num+=1、set /a num-=1、set /a num*=1 和 set /a num/=1,這些表示累加、累減、累乘、累除,步長都是1,展開后的完整寫法為:set /a num=num+1、set /a num=num-1、set /a num=num*1 和 set /a num=num/1(set /a 語句中,變量引用可以忽略百分號對或感嘆號對,set /a num=%num%+1 與 set /a num=num+1 等同)
二、batch的流程控制
2.1 if命令
IF 條件判斷語句,語法格式如下:
IF [NOT] ERRORLEVEL number command
IF [NOT] string1==string2 command
IF [NOT] EXIST filename command
(1) IF [NOT] ERRORLEVEL number command
IF ERRORLEVEL這個句子必須放在某一個命令的后面,執(zhí)行命令后由IF ERRORLEVEL 來判斷命令的返回值。Number的數(shù)字取值范圍0~255,判斷時值的排列順序應(yīng)該由大到小。返回的值大于等于指定的值時,條件成立。
例:
@echo off
dir c:
rem退出代碼為>=1就跳至標題1處執(zhí)行,>=0就跳至標題0處執(zhí)行
IF ERRORLEVEL 1 goto 1
IF ERRORLEVEL 0 goto 0
Rem 上面的兩行不可交換位置,否則失敗了也顯示成功。
:0
echo 命令執(zhí)行成功!
Rem 程序執(zhí)行完畢跳至標題exit處退出
goto exit
:1
echo 命令執(zhí)行失?。?Rem 程序執(zhí)行完畢跳至標題exit處退出
goto exit
:exit
pause
運行顯示:命令執(zhí)行成功!
(2) IF [NOT] string1==string2 command
string1和string2都為字符的數(shù)據(jù),英文內(nèi)字符的大小寫將看作不同,這個條件中的等于號必須是兩個(絕對相等的意思)
條件相等后即執(zhí)行后面的command
檢測當前變量的值做出判斷,為了防止字符串中含有空格,可用以下格式
if [NOT] {string1}=={string2} command
if [NOT] [string1]==[string2] command
if [NOT] "string1"=="string2" command
這種寫法實際上將括號或引號當成字符串的一部分了,只要等號左右兩邊一致就行了,比如下面的寫法就不行:
if {string1}==[string2] command
(3) IF [NOT] EXIST filename command
EXIST filename為文件或目錄存在的意思
echo off
IF EXIST autoexec.bat echo 文件存在!
IF not EXIST autoexec.bat echo 文件不存在!
2.2 for 命令
1. 基本格式
FOR %%variable IN (set) DO command [command-parameters]
%%variable 指定一個單一字母表示可替換的參數(shù)。
(set) 指定一個或一組文件。可以使用通配符。
command 指定對每個文件執(zhí)行的命令。
command-parameters
為特定命令指定參數(shù)或命令行開關(guān)。
參數(shù):FOR有4個參數(shù) /d /l /r /f 下面用例子解釋
2. 參數(shù) /d
FOR /D %%variable IN (set) DO command [command-parameters]
如果集中包含通配符,則指定與目錄名匹配,而不與文件
名匹配。
如果 Set (也就是我上面寫的 "相關(guān)文件或命令") 包含通配符(* 和 ?),將對與 Set 相匹配的每個目錄(而不是指定目錄中的文件組)執(zhí)行指定的 Command。
這個參數(shù)主要用于目錄搜索,不會搜索文件,看這樣的例子
@echo off
for /d %%i in (c:\*) do echo %%i
pause
運行會把C盤根目錄下的全部目錄名字打印出來,而文件名字一個也不顯示!
在來一個,比如我們要把當前路徑下文件夾的名字只有1-3個字母的打出來
@echo off
for /d %%i in (???) do echo %%i
pause
這樣的話如果你當前目錄下有目錄名字只有1-3個字母的,就會顯示出來,沒有就不顯示了
這里解釋下*號和?號的作用,*號表示任意N個字符,而?號只表示任意一個字符
知道作用了,給大家個思考題目!
@echo off
for /d %%i in (window?) do echo %%i
pause
保存到C盤下執(zhí)行,會顯示什么呢?自己看吧! 顯示:windows
/D參數(shù)只能顯示當前目錄下的目錄名字。
3. 參數(shù) /R
FOR /R [[drive:]path] %%variable IN (set) DO command [command-parameters]
檢查以 [drive:]path 為根的目錄樹,指向每個目錄中的
FOR 語句。如果在 /R 后沒有指定目錄,則使用當前
目錄。如果集僅為一個單點(.)字符,則枚舉該目錄樹。
遞歸
上面我們知道,/D只能顯示當前路徑下的目錄名字,那么現(xiàn)在這個/R也是和目錄有關(guān),他能干嘛呢?放心他比/D強大多了!
他可以把當前或者你指定路徑下的文件名字全部讀取,注意是文件名字,有什么用看例子!
請注意2點:
1、set中的文件名如果含有通配符(?或*),則列舉/R參數(shù)指定的目錄及其下面的所用子目錄中與set相符合的所有文件,無相符文件的目錄則不列舉。
2、相反,如果set中為具體文件名,不含通配符,則枚舉該目錄樹(即列舉該目錄及其下面的所有子目錄),而不管set中的指定文件是否存在。這與前面所說的單點(.)枚舉目錄樹是一個道理,單點代表當前目錄,也可視為一個文件。
例:
@echo off
for /r c:\ %%i in (*.exe) do echo %%i
pause
咱們把這個BAT保存到D盤隨便哪里然后執(zhí)行,我會就會看到,他把C盤根目錄,和每個目錄的子目錄下面全部的EXE文件都列出來了
例:
@echo off
for /r %%i in (*.exe) do @echo %%i
pause
參數(shù)不一樣了吧!這個命令前面沒加那個C:\也就是搜索路徑,這樣他就會以當前目錄為搜索路徑,比如你這個BAT你把他放在d:\test目錄下執(zhí)行,那么他就會把D:\test目錄和他下面的子目錄的全部EXE文件列出來!!!
例:
@echo off
for /r c:\ %%i in (boot.ini) do echo %%i
pause
運行本例發(fā)現(xiàn)枚舉了c盤所有目錄,為了只列舉boot.ini存在的目錄,可改成下面這樣:
@echo off
for /r c:\ %%i in (boot.ini) do if exist %%i echo %%i
pause
4. 參數(shù) /L
FOR /L %%variable IN (start,step,end) DO command [command-parameters]
該集表示以增量形式從開始到結(jié)束的一個數(shù)字序列。
因此,(1,1,5) 將產(chǎn)生序列 1 2 3 4 5,(5,-1,1) 將產(chǎn)生
序列 (5 4 3 2 1)。
使用迭代變量設(shè)置起始值 (Start#),然后逐步執(zhí)行一組范圍的值,直到該值超過所設(shè)置的終止值 (End#)。/L 將通過對 Start# 與 End# 進行比較來執(zhí)行迭代變量。如果 Start# 小于 End#,就會執(zhí)行該命令。如果迭代變量超過 End#,則命令解釋程序退出此循環(huán)。還可以使用負的 Step# 以遞減數(shù)值的方式逐步執(zhí)行此范圍內(nèi)的值。例如,(1,1,5) 生成序列 1 2 3 4 5,而 (5,-1,1) 則生成序列 (5 4 3 2 1)。語法是:
@echo off
for /l %%i in (1,1,5) do @echo %%i
pause
保存執(zhí)行看效果,他會打印從1 2 3 4 5 這樣5個數(shù)字
更加詳細的信息參考文獻【3】,這里只對流程控制有個基本的了解就可以了。
三、設(shè)置變量等
3.1 set
1. 設(shè)置自定義變量
代碼如下:
@echo off
set var=我是值
echo %var%
pause
2. 設(shè)置自定義變量,并接受用戶輸入作為值
代碼如下:
@echo off
@echo off
set /p var=請輸入變量的值:
if %var% == 1 echo 您輸入了 1 ~_~
pause
3. SET /A expression
set的/A參數(shù)就是讓SET可以支持數(shù)學(xué)符號進行加減等一些數(shù)學(xué)運算! 支持的數(shù)學(xué)運算包含(優(yōu)先權(quán)遞減):
() - 分組
! ~ - - 一元運算符
* / % - 算數(shù)運算符
+ - - 算數(shù)運算符
<< >> - 邏輯移位
& - 按位“與”
^ - 按位“異”
| - 按位“或”
= *= /= %= += -= - 賦值
&= ^= |= <<= >>=
, - 表達式分隔符
Batch代碼
代碼如下:
set /a var=2 - 1 結(jié)果是多少呢?如果你看不到結(jié)果就echo %var%.....
set /a var=2 * 2 乘法運算
set /a var=2 / 2 除法運算
set /a var=(1+1) + (1+1) 結(jié)果等于4 看得懂吧!
set /a a=1+1,b=2+1,c=3+1 運行后會顯示一個4,但我們用
echo %a% %b% %c%后看結(jié)果,會發(fā)現(xiàn)其他數(shù)學(xué)運算也有效果!,這就是"斗"號的作用!
有時候我們需要直接在原變量進行加減操作就可以用這種語法
set /a var+=1 這樣的語法對應(yīng)原始語法就是set /a var = %var% + 1
都是一樣的結(jié)果。
對于"邏輯或取余操作符",需要把他們用雙引號引起來,看例子
Batch代碼
代碼如下:
set /a var= 1 "&" 1 這樣結(jié)果就顯示出來了,其他邏輯或取余操作符用法
set /a var= 1 "+" 1 異運算
set /a var= 1 "%" 1 取模運算
set /a var= 2 "<<" 2 次方運算
set /a var= 4 ">>" 2 這個不太記得數(shù)學(xué)里的叫法....
4. 替換變量值的內(nèi)容
語法:set newVar="oldVar:str1=str2%
將變量oldVar的值中的str1替換成str2,并將替換后的變量值賦給newVar.
看例子
代碼如下:
@echo off
set a=bbs.verybat.cn
echo 替換前的值: "%a%"
set var=%a:bbs=sss%
echo 替換后的值: "%var%"
pause
對比一下,我們發(fā)現(xiàn)他把變量%a%的bbs給替換掉了,換成了sss.
5.字符串截取
1、%Var:~start,len%
注意:從0開始。
例如:
代碼如下:
@echo off
set a=www.jb51.net
set var=%a:~1,2%
echo %var%
pause
輸出結(jié)果是:ww
2、%Var:~-len%
截取倒數(shù)len位
3、%Var:~0,-len%
截取從第一位開始,倒數(shù)第len位結(jié)束的值。
例子
代碼如下:
@echo off
set a=www.jb51.net
set var=%a:~0,-3%
echo %var%
pause
四、例子
下面是自己寫的例子,對batch有了了解之后,就實現(xiàn)一個小任務(wù)。
學(xué)校里可以通過代理來共享網(wǎng)絡(luò),只要某臺電腦聯(lián)網(wǎng)并開啟了CCPROXY,那么只要知道這一臺電腦的IP地址,那么就能夠?qū)崿F(xiàn)免費上網(wǎng)。
這個任務(wù)包含兩個方面
1.需要知道局域網(wǎng)中哪臺電腦連入了了。
這個可以通過ping這條命令來實現(xiàn)。根據(jù)計算機網(wǎng)絡(luò)知識知道,學(xué)校里的局域網(wǎng)的地址范圍是172.16.0.0.-172.31.255.255.
那么寫個bat文件遍歷所有IP地址,把那些能夠ping通的保存下來就可以了。
2.如何測試ping通的電腦開啟了ccproxy。
可以通過proxifier這個軟件來測試,但是存在問題是測試比較麻煩,需要配置和check。暫時還沒能寫個腳本。
先解決第一個問題
@echo off
setlocal enabledelayedexpansion
for /l %%a in (16,1,31) do (
for /l %%b in (0,1,255) do (
for /l %%c in (0,1,255) do (
ping 172.%%a.%%b.%%c -n 2 -w 100
if not !errorlevel!==0 (
:: >>"test_block.txt" echo IP:172.%%a.%%b.%%c cannot ping )
if not !errorlevel!==1 (
>>"test_passing.txt" echo IP:172.%%a.%%b.%%c can ping )
)
)
)
echo test finished !
pause
程序比較簡單,3層循環(huán),按照IP地址范圍測試,測試成功到保存的test_passing.txt文件中。雖然設(shè)置了回顯請求數(shù)位2,并且等待超時時間為100ms,但是還是運行很久,可以進一步減少IP地址范圍,如一個實驗室內(nèi)。
參考文獻
【1】:http://zh.wikipedia.org/wiki/DOS
【2】:http://www.jb51.net/list/list_106_1.htm
【3】:http://www.rzrgm.cn/glaivelee/archive/2009/10/07/1578737.html




浙公網(wǎng)安備 33010602011771號