批處理
說明
- 面向程序編程.
實際
- 提高效率.
內容
- 若干指令.
- 需要反覆執行.
- 保存到文件中方便執行.
啓動
cmd
- 到
C:\Windows\System32
下雙擊cmd.exe
指令.Win+r
輸入cmd
win
搜索cmd
.特性
功能 特點 輸入 交互式,實時決策執行. 判斷 for,if,while,switch
都有.基本類型 數字,字符串,數組,函數 匹配 正則表達式 併發 默認串行, start
並行.goto
指令跳轉 位運算 與或非 邏輯運算 and or not
,大於小於等於字符串 子串,長度,替換,裁剪 文件 存在判斷 (if exist filename)
,修改屬性,創建刪除.延遲擴張
- 兩種解析:一種是讀取一行就立即將
%
裏面的變量解析.但是這類在一些場景不合適.- 另一種是延遲擴張:即在執行語句的時候擴張. 這樣就允許組合表達式.
- 類比
makefile
的secondexpansion
.
腳本
文件名後綴
BAT
CMD
執行
BAT
雙擊執行.cmd
中執行.執行
bat
cmd
中輸入完整文件路徑.cmd => cd /path/to/bat => xxx.bat
- 修改環境變量
PATH=%PATH%;path\to\bat => 執行xxx.bat
. (和上面兩個一樣的效果)- 路徑下雙擊文件.
常用指令
腳本
指令 作用 案例 ver
當前 msdos
版本.cmd
啓動時的第一行assoc
後綴綁定程序. foxitreader
打開.cls
清理屏幕 等價 clear
,cls
清理屏幕和緩存path
環境變量,指定指令搜索路徑. echo %path%
rem
remark
,表示註釋,不輸出,啥也不做.start
並行執行 開啓新的 cmd
窗口或程序driverquery
查看驅動詳情 ipconfig
網絡信息管理,釋放和重新分配.查看信息等. systeminfo
查看系統信息,系統信息,處理器,網卡,內存 編程
指令 作用 案例 pause
暫停,等待輸入任意符號. 常在腳本最後添加,查看執行輸出. prompt
設置提示欄 默認情況下,輸入前面是當前路徑. $G == >
choice
從給定的選擇中任選一,一般是阿拉伯字母. title
命名窗口名稱. set
查看已經定義的所有變量及值 文件操作,不涉及目錄
指令 作用 案例 copy
文件拷貝,不涉及路徑拷貝 無 del
文件刪除,不涉及目錄 支持嵌套遞歸. del /s *.txt
attrib
修改文件屬性 類似 chmod
.attrib +r file
comp
比較兩個文件的大小. more
查看文件內容 目錄操作
指令 作用 案例 cd
無參查看路徑,有參更換路徑. cd=pwd
,cd xx=cd xx
dir
查看路徑下文件和文件夾 類似 ls
.支持查看子文件dir /s
md
創建目錄 類似 mkdir
,支持同時創建多個文件夾.文件和目錄
指令 作用 案例 move
移動或重命名 rd
默認僅僅刪除文件夾,刪除文件夾前不能爲空. /s
刪除文件默認文件夾操作,選項支持文件操作. ren
重命名,文件夾和文件都支持. find
從文件中搜索字符串 xcopy
文件和文件夾都支持,建議用這個. sh=cp
tree
樹形的方式查看文件夾子文件夾. tree
可以分級,可以選擇是否查看文件.默認僅查看目錄.時間
指令 作用 案例 date
查看日期 echo %date%
time
查看時間 echo $time%
輸出
開關
echo on
:輸出執行的腳本。echo off
:不輸出執行的腳本。
@
- 從當前指令開始生效。
- 一般用於
@echo off
.
代碼
創建修改
notepad
打開,輸入echo ok && pause
,保存爲xx.cmd或xxx.bat
.- 點擊文件,右鍵
edit
,編輯.命名
- 儘量不要加空格.
- 儘量不要和內部指令重名.
執行和輸出
說明
- 指的是在
cmd
中不要輸出指令.普通
指令
dir /b
輸出
D:\money\battst>ait.bat D:\money\battst>dir /b ait.bat dd good D:\money\battst>
關閉指令輸出
關閉之後
echo off dir /b
輸出
D:\money\battst>ait.bat D:\money\battst>echo off ait.bat dd good D:\money\battst>
echo off
沒有生效,執行後才生效所以輸出了.dir /b
生效了,沒有輸出指令.最終版本
@echo off dir /b
D:\money\battst>ait.bat ait.bat dd good D:\money\battst>
最終版本,一條指令都沒有輸出.
@
就表示,echo off
的影響從當前行開始.註釋
說明
- 當一個批處理文件太大,往往是需要註釋的.
註釋方式
:: comment
rem comment
變量
來源
- 兩類: 參數類型變量,自動生成. 普通變量,自己定義.
參數變量
編號
%0 %1 %2 %3 ... %9
,最多9
個.- 可以通過
SHIFT
提升上限.即起始下標+1
,args[0] = args[shift_time + 0]
.- 和普通程序一樣.
變量輸出
@echo off dir /b echo %0 echo %1 echo %2
D:\money\battst>ait.bat 3 2 ait.bat dd good ait.bat 3 2
0
是文件名,1,2
就是參數.編號大於參數
@echo off dir /b echo %0 echo %1 echo %2
D:\money\battst>ait.bat 3 ait.bat dd good ait.bat 3 ECHO 處於關閉狀態。
因爲參數只有一個,
echo %2
的實際是echo
,提示錯誤.提升上限.
``cmd @echo off echo %0 echo %1 echo %10% shift echo %1 shift echo %1 shift echo %1 shift echo %1
```shell D:\money\battst>ait.bat 99 88 77 66 55 44 33 22 11 46 ait.bat 99 990 88 77 66 55
shift
一次,0-9
指向的位置就+1
.
set
定義變量
說明
set
定義變量.- 默認定義字符型,加選項可以定義數字型.
- 即加選項對後面的字符串進行不同的解析處理.
(會棧的也可以自己實現這種)
字符定義和數字
@echo off set aaa=1 set /a bbb=%aaa% + %aaa% echo %aaa% %bbb%
D:\money\battst>ait.bat 1 2
/a
則將後面替換後的的字符串進行算術解析.(怎麼解析沒有研究過.)
aaa
就是字符串,但是bbb
的結果是字符串按照算術解析的方式得到的結果。字符串方式也可以定義數字,但是運算就需要用
set /a
的方式.作用域
說明
- 有局部變量和全局變量.
setlocal
之後,endlocal,exit,eof
之前定義的都是局部變量,退出範圍就恢復之前的值.
bat
中的變量影響當前cmd
,執行完了之後還在.案例
@echo off set aaa=1 setlocal enabledelayedexpansion set aaa=2 echo %aaa% endlocal echo %aaa%
注意
aaa
之前是1
,局部輸出2
,endlocal
之後恢復.D:\money\battst>ait.bat 2 1
退出後無效
這裏改成
ccc
是因爲aaa
執行後在環境變量中已經有定義.set | find "aaa"
可查看.@echo off setlocal enabledelayedexpansion set ccc=2 echo %ccc% endlocal echo %ccc%
D:\money\battst>ait.bat 2 ECHO 處於關閉狀態。
- 之前演示的是定義後恢復值,這裏演示退出後未定義.
環境變量
set
查看已經定義的.和具體值.訪問和普通變量一樣.
字符串
說明
- 全都是字符串.
set /a xxx = xxx + xxx
的時候才進行算術運算,其他都是字符串操作.定義
- 變量名和等號之間不能有空格.
表達式 結果 var = value
var
與=
之間有空格不行var= value
沒有空格,行. 字符串和數字
@echo off set sss=2 set /a bbb=%sss% * 5 + 1000 echo %bbb% set ccc=%bbb% + 10 echo %ccc% set /a ddd=%ccc% echo %ddd% echo %ddd:~2%
D:\money\battst>ait.bat 1010 1010 + 10 1020 20
值爲空判斷
@echo off set sss= if "%sss%" == "" (echo empty) else (echo not empty) set sss= if "%sss%" == "" (echo empty) else (echo not empty)
D:\money\battst>ait.bat not empty empty
第一個有個空格,第二個是真的空.
子串
@echo off set str=cool echo %str:~1%
D:\money\battst>ait.bat ool
子串格式說明
功能 案例 %str:~start,len%
start
起始位置,len
長度.%str:~1,1% => o
%str:~start%
start
起始位置,這個位置以後的所有.%str:~1% => ool
%str:~start,-pos%
start
起始位置,-pos
標示倒數第幾個爲止,不包含.%str:~1,-1% => oo
%str:~-pos%
-pos
,從倒數第pos
個起,包含.%str:~-1% => l
%str:~-pos,len%
-pos
開始,長度爲len
的子串%str:~-3,2% => oo
%str:~-pos,-end
-pos
開始,到倒數第end
的一個,end
不包含.%str:~-3,-1% => oo
替換
@echo off set aaa=what the fuck echo %aaa% echo %aaa:fuck=f*k%
D:\money\battst>ait.bat what the fuck what the f*k
字符串長度
rem @echo off set str=cool call :func_strlen str retlen echo %retlen% pause exit /b :: 函數定義 :func_strlen setlocal enabledelayedexpansion :strLen_Loop if not "!%1:~%len%!" == "" set /a len+=1 & goto :strLen_Loop (endlocal & set %2=%len%) goto :eof
bat
沒有求長度的函數,使用循環截取子串判斷是否爲字符串末尾.:func_strlen
自定義函數定義.:srLen_Loop
循環.:func_strlen
函數定義.endlocal
臨時變量末尾set %2=%len%
,給%2
的變量名賦值.所以retlen
有值.goto :eof
返回,參考鏈接https://stackoverflow.com/questions/37515901/where-does-goto-eof-return-to
.call :label
會模擬創建一個新的bat
文件再執行腳本,goto :eof
就是退出文件,而這裏是退出模擬文件,即返回了之前調用位置.exit /b
不退出就會死循環,執行下面的函數並一直執行.及無限的調用函數退出.D:\money\battst>ait.bat D:\money\battst>rem @echo off D:\money\battst>set str=cool D:\money\battst>call :func_strlen str retlen D:\money\battst>setlocal enabledelayedexpansion D:\money\battst>if not "!str:~!" == "" set /a len+=1 & goto :strLen_Loop D:\money\battst>if not "!str:~1!" == "" set /a len+=1 & goto :strLen_Loop D:\money\battst>if not "!str:~2!" == "" set /a len+=1 & goto :strLen_Loop D:\money\battst>if not "!str:~3!" == "" set /a len+=1 & goto :strLen_Loop D:\money\battst>if not "!str:~4!" == "" set /a len+=1 & goto :strLen_Loop D:\money\battst>(endlocal & set retlen=4 ) D:\money\battst>goto :eof D:\money\battst>echo 4 4 D:\money\battst>pause 請按任意鍵繼續. . . D:\money\battst>exit /b
數組
說明
- 其實也是字符串,不過是字符串拼接.
- 可以用
set
查看.- 不過多了這個編程概念,下標一般從
0
開始定義
@echo off for /l %%i in (1,1,10) do set sss[%%i]=%%i set | find "sss"
D:\money\battst>ait.bat sss[10]=10 sss[1]=1 sss[2]=2 sss[3]=3 sss[4]=4 sss[5]=5 sss[6]=6 sss[7]=7 sss[8]=8 sss[9]=9
遍歷
@echo off for /l %%i in (1,1,10) do set sss[%%i]=%%i set | find "sss" setlocal enabledelayedexpansion for /l %%i in (1,1,10) do echo !sss[%%i]!
setlocal enabledelayedexpansion
使用了延遲擴展,延遲擴展用!
來表示.%
在第一次的時候會擴展,而!
則在第二次的時候進行擴展,D:\money\battst>ait.bat ssss=abcdefg sss[10]=10 sss[1]=1 sss[2]=2 sss[3]=3 sss[4]=4 sss[5]=5 sss[6]=6 sss[7]=7 sss[8]=8 sss[9]=9 1 2 3 4 5 6 7 8 9 10
長度
數組需要從
0
定義,否則長度不準確.判斷類似字符串,但是因爲是變量,所以可以用關鍵字
define
.長度案例
@echo off for /l %%i in (1,1,10) do set sss[%%i]=%%i setlocal enabledelayedexpansion for /l %%i in (1,1,100) do if defined sss[%%i] (set /a len+=1) else (goto :out) :out echo %len%
D:\money\battst>ait.bat 10
**起始下表不是從
0
開始,其實不標準.
決策
解析
- 按行解析,如果要多行,就要在行末尾表示行未結束.
如何處理數字和字符串
- 主要根據運算符有關.
- 運算符決定了符號兩邊的解析方式.
if
- 支持
if,if else, if if
等.變量操作
defined
判斷是否定義.
==
- 等於
errorlevel n
- 上一次指令的退出嘛是否是
n
.n
是自己的數字.
%errorlevel%
- 上一條指令的返回值.
- 和
call
可以一起用call other.cmd
goto
- 跳轉到指定的位置.
- 注意
call
裏面的goto
.見前面.語法解析
@echo off if 1 == 1 (echo nice) else (echo good) if 1 == 1 (echo nice) else ( echo good) if 1 == 1 ( echo nice ) else ( echo good ) if 1 == 1 (echo nice ) else ( echo good) ::else ::(echo good)
需要在行末尾表示行結束,
else
後啥都沒有就是錯誤的.
運算符
使用場景
- 一般用於條件判斷。
- 不多也可以用於其他場景
總覽
分類 說明 數學運算 + - * / %
,不支持浮點關係運算 >gtr;>=geq;==equ;<lss;<=leq;
使用英文縮寫,而不是>,<
之類.==
比較特殊.a < A
,a < b
,110 > 12
.和字符值無關.數字按數字規則,字符串按字符串.邏輯運算 and or not
,可以用於拼接bool
表達式,即if
.賦值運算符 += -= *= /= %=
,算術運算.位運算 `& 重定向 `> >> < 2> 1>
退出碼
%errorlevel%
函數定義
函數要素
要素 說明 聲明 :function_name
,和goto
的位置標籤一樣.定義 若干個指令 返回值 exit /b code
返回獲取返回值 %errorlevel%
獲取執行函數的返回值.參數賦值 endlocal & set %2=%var1%
參數 call :func_name arg1 arg2 arg3
獲取參數 %1,%~1
exit /b
- 僅僅退出批處理腳本,而不是退出
cmd.exe
call :function_name
- 調用函數,可以看成是在個新的
cmd
裏面執行.- 但是變量會共享,所以一般會添加
setlocal,endlocal
.- 而且
function
裏面可以定義:label
.案例
::@echo off call :func_test 200 retlen echo %retlen% pause exit /b 2 :func_test setlocal enabledelayedexpansion set /a dd=%1 :while if %dd% gtr 0 ( set /a dd/=10 set /a cnt+=1 goto :while ) endlocal & set %2=%cnt% goto :eof
- 功能是判斷一個數佔幾位.
endlocal &
是一句,會立即解析.局部變量
- 在函數中,局部變量是很重要的.
- 可以避免與外界變量衝突
遞歸
::@echo off call :func_test 200 echo %errorlevel% pause exit /b 2 :func_test setlocal enabledelayedexpansion if %1% gtr 0 ( set /a tmp=%1%/10 call :func_test %tmp% set /a ret=!errorlevel!+1 exit /b !ret! )
- 和上面一樣的功能,一樣的結果.
- 這裏有
enabledelayedexpansion
才能執行成功,因爲是執行的時候才擴張.
循環
常見格式
for {%% | %}<variable> in (<set>) do <command> [<commandlineoptions>]
%%var
或%var
的方式聲明變量.in
固定格式。(<set>)
,()
括號裏面是集合,集合有很多種.command
循環體.
for in do
固定格式.
set
範圍
/l : loop
,start,step,end
.end
包含.@echo off for /l %%i in (1,2,10) do ( echo %%i )
D:\money\battst>ait.bat 1 3 5 7 9
路徑
/d : directory
@echo off for /d %%i in (*) do ( echo %%i )
D:\money\battst>ait.bat dd good
路徑
D:\money\battst>tree D:. ├─dd └─good
文件
/r :recursive
遞歸查看
@echo off for /r %%i in (*) do ( echo "%%i")
D:\money\battst>ait.bat "D:\money\battst\ait.bat" "D:\money\battst\aitd.bat" "D:\money\battst\dynamic_sub.bat" "D:\money\battst\dd\1.txt"
D:\money\battst>tree /f 卷 有錢人的固態 的文件夾 PATH 列表 卷序列號爲 DED3-62FD D:. │ ait.bat │ aitd.bat │ dynamic_sub.bat │ ├─dd │ 1.txt │ └─good
一般不用
usebackq
- 即在括號內用反括號當成是指令執行.
/f
說明
- 文件操作,按行讀取,相關的開關進行按行解析.
開關說明
字段 說明 eol
以 eol
開頭的行忽略.skip
前 n
行忽略,前n
行丟棄掉.delims
對一行數據進行拆分.默認分隔符是空格和 tab
.tokens
選擇由 delims
分隔後的n
個子串數組中的若干個.*;s-e;1,3,5,7
,即指定選取的下標,可以是枚舉,可以是區間,可以是*
通配符.變量 tokens
的時候,%%i
則對應取到數據的下標1
,%%j
則對應2
,%%k
則對應3
,一次類推.說明 都有默認值 操作文件
,aa,bb,cc,dd, ,ee,ff,gg,hh, ,ii,jj,kk,ll,mm oo,pp,qq,rr,ss,tt
文件查看
@echo off for /f %%i in (aa.csv) do ( echo "%%i")
D:\money\battst>ait.bat "aa,bb,cc,dd," "ee,ff,gg,hh," "ii,jj,kk,ll,mm"
eol;end of line
@echo off for /f "eol=," %%i in (aa.csv) do ( echo "%%i" )
D:\money\battst>ait.bat "oo,pp,qq,rr,ss,tt"
delims,tokens
@echo off echo ------------------------------------ for /f "delims=," %%i in (aa.csv) do ( echo "%%i") echo ------------------------------------ for /f "delims=," %%i in (aa.csv) do ( echo "%%i" "%%j" "%%k" "%%l") echo ------------------------------------ for /f "delims=, tokens=*" %%i in (aa.csv) do ( echo "%%i" "%%j" "%%k" "%%l") echo ------------------------------------ for /f "delims=, tokens=1-3,4" %%i in (aa.csv) do ( echo "%%i" "%%j" "%%k" "%%l") echo ------------------------------------ for /f "delims=, tokens=1-4" %%i in (aa.csv) do ( echo "%%i" "%%j" "%%k" "%%l")
D:\money\battst>ait.bat "aa" "ee" "ii" "oo" ------------------------------------ "aa" "%j" "%k" "%l" "ee" "%j" "%k" "%l" "ii" "%j" "%k" "%l" "oo" "%j" "%k" "%l" ------------------------------------ "aa,bb,cc,dd," "%j" "%k" "%l" "ee,ff,gg,hh," "%j" "%k" "%l" "ii,jj,kk,ll,mm" "%j" "%k" "%l" "oo,pp,qq,rr,ss,tt" "%j" "%k" "%l" ------------------------------------ "aa" "bb" "cc" "dd" "ee" "ff" "gg" "hh" "ii" "jj" "kk" "ll" "oo" "pp" "qq" "rr" ------------------------------------ "aa" "bb" "cc" "dd" "ee" "ff" "gg" "hh" "ii" "jj" "kk" "ll" "oo" "pp" "qq" "rr"
分析
None = [0] = s.split(",")[0] * = [0] = ",".join(s.split(",")) range = [:] = s.split(",")
(set)
類型 說明 (filename)
字符串來自文件. 可以多個文件 "str"
字符串來自給定字符串 'cmd'
字符串來自指令輸出