批處理(bat)命令學習的一些總結

這篇筆記是我對批處理學習的一些總結,能在系統幫助裏找到的內容我就不寫了,太偏門的也不寫,只寫些我的感受很好用的技巧,大部分屬於整理html

1、set 篇:算法

一、set(無開關)dom

set .=test函數

set.oop

::若一個變量以:\.這三個與路徑相關的符號開頭,用set查看以該字符打頭的變量時能夠省去一個空格。學習

echo %tmp:*\=%測試

::顯示tmp變量第一個\以後的部分,其他變量替換與變量偏移太簡單不解釋編碼

二、set /p 變量名=註釋<設備名加密

當設備名爲文件時,由於文件中換行符與回車符伴生,因此只取文件第一行做爲var變量的內容,可是不超過1024字節;而當設備名爲nul或者com3時,只顯示不換行的註釋,這種狀況下能夠省略變量名(如:set /p=Hello World日誌

三、set /a,最具技巧的命令之一

set /a n=1,m=2

::同時把不一樣數值分別賦予兩個變量

set /a a=b=c=d=e=f=1

::用一條算式爲多個變量同時賦值

set /a "1/n" 2>nul||echo 變量n非純數字或爲零

::利用分母不能爲0的特徵,用set判斷一個變量是否爲非零純數字

set n=1

set /a "n=!!123|!!234&!!0"

::位運算,!、^、|和&經常使用於布爾運算,而邏輯位移經常使用於二進制運算(>>還可判斷數值是否爲負,見下例)

set /a n=-100,"1/(-100>>31)"||echo 變量n爲負數

::順應cmd中的正負數存儲特色,能夠用邏輯位移實現判斷正負數的「布爾運算」,能夠衍生出繁多的算法,好比稍加改動就能夠比較兩數甚至多個數的大小

set /a n=~-100

::利用~將全部二進制的一、0逆轉,負號在後或在前配合能夠實現簡單加1或減1,這個技巧主要用來減小括號的使用,由於~號與負號的優先級都是高於算數運算符的

set /a test=%test:~5,1%-0

::能夠避免%test:~5,1%爲空時出錯的狀況

set /a 十進制=0x十六進制,十進制=0八進制

::快速將十六進制與八進制數轉爲十進制,惋惜沒有二進制...

:loop

set /a n+=1001

echo %n:~-3%

goto loop

::這比常規的補位方法更優越

for %%a in (test 123 ABC test @#$ 123) do set /a ".%%a+=1"

set .|findstr /v /e "=1"

::經典的獲取字符串的重複次數的方案

2、for 篇:

這是批處理中最強的內部命令,沒有之一!

一、for(無開關)

for %%a in (c:\*.*) do echo %%a

::顯示C盤根目錄下全部非隱藏、非系統屬性文件

for %%a in (.\..) do echo %%~nxa

::顯示上一級目錄的文件夾名

set str=123,234,345

set str=%str:,=\%

for %%a in (%str%\..) do echo %%~nxa

::用前一個技巧,巧取倒數第二段字符串,與for /f "delims=\"相映成趣

for %%a in (*.txt) do (

for /f "useback delims=" %%b in ("%%a") do (

set str=%%b

for %%c in ("!str:分隔符=" "!") do (

for /f "tokens=1*" %%d in (%%c) do echo %%~d

)

)

)

::不帶參數的for與for /f配合,威力極大,僅舉此一例

for %%a in (123) do for %%a in (234) do for %%a in (345) do echo %%a

::其實若是隻讀取最後一層for的參數,即便多層for嵌套也可使用一樣的參數,好比%%a

for %%z in (!tmp!) do echo !%%z!

::目前已知的擺脫call實現多層變量嵌套的最好方法,很多人用

二、for /l

for /l %%a in () do echo 

::無限循環,步數爲0也是同樣的效果,可是沒這個簡潔

for /l %%a in (-4 1) do echo %%a

::for /l中的三項參數從左至右的三位分別是初始值、步數、終止點,當用戶給定的數量不足時,將按從右至左的順序把不足的一項賦爲0

三、for /d /r

for /r /d %%a in (*) do echo %%a

::能夠遍歷全部子文件夾,之因此能夠聯用r開關和d開關是由於它們的參數有交集,l開關和f開關就不行了。

四、for /f

for /f自己的技巧並非特別多,它的優點是可以將其餘命令的輸出做爲輸入來分析,因此for /f能夠說是當之無愧的內部命令之王

for /f "tokens=* delims=0123" %%a in ("0000123456") do echo %%a

::去除前綴的n個字符

for /f "skip=99" %%a in (1.txt) do echo 1.txt至少100行

::之前看到某版主寫的,印象頗深。

for /l %%a in (1 1 10) do (

for /f "tokens=1,2* delims=\" %%a in ("!tmp!") do (

for %%c in (%%a %%b) do echo %%c

set tmp=%%c

)

)

::將tokens的取值範圍無限拓展

set tmp=123=234=345=456

for /l %%a in (1 1 40) do (

for /f "tokens=1,2* delims==" %%a in ("!tmp!") do (

set str=!str!,%%a,%%b

set tmp=%%c

)

)

echo %str:~1%

::有時候set變量替換是沒法替換一些特殊字符的,此時能夠用for /f處理

set test=d:\test\

for %%a in (test.*) do (

if "%%~za" neq "%%~z$test:a" replace /p /u "%%a" "%%~dp$test:a"

)

::判斷當前目錄下以test爲名的文件是否在d:\test\文件夾下存在同名文件,若是存在且大小不一樣、修改日期更早,則替換之,不然不作處理。for幫助信息中的「%%~dp$path:a」參數彷佛沒見人用過,雖然它的適用範圍很狹隘,可是特定的狀況下不妨一試。

setlocal enabledelayedexpansion

set t=tmp

set @=t

for /f %%a in ('echo !%@%!') do echo !%%a!

::另外一種三層嵌套方法,其實不實用。

3、findstr 篇

我最鍾愛的命令,惋惜外部命令的啓動速度太慢,因此實際運用時較少露面。

findstr /s /m .* *.*

::其實findstr也是一個dir,雖然比dir慢些,卻多了查找文件內容的功能

findstr /n .* 1.txt|findstr "^5000:"

::很是實用的取指定行的方法,配合正則能夠取指定範圍以內的行

set /p n=請輸入數字或大小寫字母

(echo !n!)|findstr /i "[0-9a-Z]"&&echo 輸入有誤!

::這個夠實用吧?不解釋

dir|findstr ['-Z]

::利用findstr和if命令中字符的實際大小順序實現查找含有寬字符的行

findstr /x ".........." 1.txt

::查找1.txt中10字節的行

(type 1.txt&echo;)|findstr /o .*|more +1

::加上for,很容易獲取1.txt每行的字節數

findstr>1.txt /m /p .* *.*

dir /b /a-d|findstr>2.txt /v /i /m /g:1.txt

::獲取含有不可打印字符的文件名,關鍵是findstr取集

findstr "^Rar!" /g:1.txt

::此處1.txt是上個技巧的1.txt,內容是全部含不可打印字符的文件列表,此技巧可搜索rar文件,雖然簡單,可是至今也未出錯過,原創。

more>tmp +2 1.txt

findstr>前兩行.txt /x /v /g:1.txt 2.txt

::有時候可用此辦法獲取前幾行,固然,絕大部分狀況下沒有for /f合適,並且存在特殊字符bug

@echo off

findstr /n .* 1.txt>tmp1

find /n /v "" 2.txt|more>tmp2 +2

for /f "tokens=2*delims=]:" %%a in ('fc /n /lb10000 tmp1 tmp2^|sort') do (

echo;%%b

)

del tmp?

pause

::qzwqzw獨創用fc /n同時輸出雙文本的思路,可是存在排序有可能被打亂的缺陷,因此加了個find彌補一下

4、start、call、cmd 篇

之因此放在一塊兒,是由於這三個命令的功能有所交集

一、start

@echo off

%1 cd.>tmp

set /p=%1

%1 start /b "" %0 :(五秒後退出) tm

if not "%1"=="" goto %1

set /p n=輸入任意字符

if defined n (

del tmp

echo 您輸入的是%n%,五秒後退出。

) else echo 輸入爲空!五秒後退出。

:(五秒後退出)

ping /n 5 localhost>nul

if exist %2p exit

pause

::妙用start /b讓set /p實現choice的延時功能,不知道哪位前輩獨創的,再次贊一個。此處%一、%2的技巧僅做點綴,我只是以爲這樣「搭積木」很好玩才強加上去的。

二、call

set a=b

set b=c

call echo %%%a%%%

::不使用變量延遲仍然能夠藉助call實現變量的延遲讀取與嵌套,可是效率上有缺陷

三、cmd

set a=b

set b=c

cmd /c echo %%%a%%%

::這證實call一個命令時的效果近似於cmd /c,兩者的區別體如今"for"和"if"這兩個命令不能用call運行,由於for和if其實可能只是關鍵字,而非真實存在的命令

set a=b

set b=c

cmd /v:on /c echo !%a%!

::不須要setlocal,照樣可使用變量延遲

%1 %0 :: echo;成功調用自身

%2

::我的很經常使用,這裏用%1和%2的技巧爲我所偏心,那個::能夠視狀況換爲rem。雖然此處並未出現cmd命令,但其實運行自身時執行的就是cmd /c %0。

@echo off

%1 cmd /v:on /c %0 ::

set n=123

echo !n!

pause

::綜合前兩個技巧實現不使用setlocal,開啓變量延遲

@echo off

set str=test測試1234

setlocal enabledelayedexpansion

for /f "delims=:; " %%a in ('((cmd /u /c echo !str!^)^&echo^;^;^)^|findstr /o ^;') do set /a n=%%a-5

for /f "delims=:" %%a in ('((echo !str!^)^&echo^;^;^)^|findstr /o ^;') do set /a d=n-%%a+3

set /a m=n/2,s=m-d

echo 共!m!個字符,!d!個單字節字符、!s!個雙字節字符

pause

::三步判斷單字符、雙字符個數的另類辦法。優點在於支持對超長字符串進行計算(此時用常規算法步驟多且難通用),缺點在於效率低。

ren 1.exe 1.bat

echo 請雙擊1.bat

::爲何這樣也能夠運行呢?由於exe的打開方式是"%1" %*,bat是cmd /c "%1" %*,因此把exe當作bat運行時,至關於cmd /c 1.exe...不過這隻適合雙擊打開,在cmd內部調用此文件的時候是當成真正的bat運行的,因此會出錯。

5、其餘命令 篇

一、xcopy比copy強大得多,最大的遺憾在於它是外部命令

xcopy /a 源文件夾 目標文件夾

::xcopy用在篩選上也很實用

xcopy /l /y /n %cd% ..

::巧取當前目錄下文件的短名,並不會真的複製

xcopy /d:1-31-2011 /l "%cd%" tmp\

::獲取修改日期在2011年1月31日之後的文件清單

xcopy /t *.txt C:\test\

::複製含有txt文件的目錄結構到C:\test

@echo 1.txt>list

xcopy /exclude:list ?.txt test\

::複製全部以單個字符爲名的文件到test文件夾

xcopy /s *.txt ..\txt\

::複製全部以txt爲名的子文件到上一級目錄中的txt文件夾

for /f "delims=" %%a in ('dir /s /b /ad^|sort -r') do rd "%%a" 2>nul

::刪除空文件夾的經典思路,利用rd默認不刪除非空文件夾的特性進序刪除空文件夾

for /d %%a in (*) do (

xcopy /q /h /r /s /k "%%a" "tmp\"

rd /s /q "%%a"

ren "tmp" "%%a"

)

::刪除空文件夾的另類方案

二、相比於前面幾個大佬級的命令,這些命令算是比較不起眼的了,因此歸在一類

copy nul+Unicode.bat 解密.bat

::用Unicode文件頭來進行編碼混淆加密的bat,能夠用這條命令解密

echo>tmp 12323412 2323242134122434 345

more /t20 tmp>對齊.txt

type 對齊.txt

pause

::more命令的t開關也有大用途,潛規則不解釋。

cmd /u /c echo 0123456789|more

::more命令會將cmd /u輸出的nul字符轉換爲空格,從而實現逐字打印一行單字節字符。

@echo off&setlocal enabledelayedexpansion

set n=32768

(for %%a in (16384 8192 4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do sort /rec !n! %0&&set /a n-=%%a||set /a n+=%%a)>nul 2>nul

echo 最長行有%n%個字符

pause

::當最長的行字符數大於128時可能能夠用這個來判斷最長行的字符數(短於128時rec開關會失效,代碼中那一大堆2的N次方就是湊字數的,實戰中能夠省掉一些),支持超長字符串,計算大文件時效率明顯優於傳統算法,新折半法來自plp626的轉帖,sort的/rec開關比較雞肋,想來想去也只想到這個用途,未見先例

ren 1.exe 1.bat

echo 請雙擊1.bat

::爲何能夠把exe改成bat後綴名運行呢?由於exe的打開方式是"%1" %*,bat是cmd /c "%1" %*,因此把exe當作bat運行時,至關於cmd /c 1.exe...不過這隻適合雙擊打開,在cmd內部調用此文件的時候是當成真正的bat運行的,因此會出錯。並且基於一樣的緣由,它還能夠改爲com或者cmd後綴名來執行。

三、再介紹一些在cmd窗口中的技巧,固然它們僅僅是「欺騙」cmd窗口,一旦輸出到文件就原形畢露:

@echo off

echo 1

echo 2

echo 3

echo 退行了

pause>nul

::這個太牛了,不知道哪位發現的

set "dq= "

(echo 二、計劃生育的重要性%dq%啊

echo 一、貫徹落實科學發展觀%dq%哇)|sort

::藉助tab鍵與退格符實現多行捆綁排序並錯行顯示,tab與退格之間的那個空格是關鍵,不然變爲退行

set /p=同一行顯示不一樣顏色:

set /p=紅底藍字

echo  黃底綠字

findstr /a:41 .* 紅底藍字?

findstr /a:62 .* 黃底綠字?

del>nul 紅底藍字 黃底綠字

pause

::常常見到的在同一行顯示不一樣顏色的辦法,不過不少人老是用    (四個退格四個空格),說明沒理解退格鍵的意義

@prompt $_

dir fuck.tmp

pause

::利用這個prompt,打開回顯後能夠同時輸出命令與命令結果,而不會有多餘內容,適合製做bat運行日誌

echo 

::這個黑色的圓點在前面的介紹中做爲配角出現過,是ansi碼中的0x07,也等同於在cmd中輸入的ctrl+G,它每次被顯示在屏幕上時都會發出「滴」的一聲,因此之後findstr *.*時必定要留神了(除非不得已,不然須要把結果顯示到窗口時建議加上/p開關),萬一不當心打印出幾萬個,你的電腦會像發電報同樣響個不停,我中招N次了...

6、cmd運行機制 篇

一、預處理機制:特殊字符優先級、語句和語塊的劃分

setlocal enabledelayedexpansion

(set n=3

set /a n=2,n=%n%+!n!+n)

::利用預處理機制,將一個變量解釋爲多個值

setlocal enabledelayedexpansion

echo ^^!

::當語句中存在變量延遲符號時,將被預處理兩次,這是必定要注意的

set str=.

set "str name=str"

for %%a in (%tmp%) do if defined %%a echo %%a 存在變量str

::利用for的參數變量在if參數劃分以後才被解釋的特色,彌補if defined對於空格變量名的兼容性缺陷,本質緣由是for和if都是特殊的函數,他們的參數設置在語塊的預處理中就已經被cmd「記住」了,以後沒法對其進行改變。

(del %0

echo 能找到我,就給你發糖

pause>nul)

::括號裏的內容被理解成一個語塊,運行其中的命令時不需從文件讀取,因此就算刪除自身仍可運行。

echo "test&pause|sort

::當一行命令中存在奇數個雙引號時,將會轉義其後全部本行字符

for /f tokens^=2delims^=^" %%a in ("123"test"456") do echo %%a

::經過對特殊字符的轉義,在for中用雙引號當分隔符

for /f tokens^=2delims^=^" %%a in (^"123"456") do echo %%a

set /p=^"""

::當一組字符串中含有奇數個雙引號時常常會出錯,解決方法是轉義其中的一個,保持有效的雙引號成對,但是引號對以內沒法用轉義符對其轉義,因此轉義符要放在引號對以外使用

set /a "1/(%random%%%2)"&&set com=||set com=/f "tokens=2"

for %com% %%a in ("123 234 345") do echo %%a

::假如隨機值爲偶數,則顯示指定字符串第二段,不然顯示整段。這裏用變量來定製命令,會比常規辦法(一條if和一條命令對應)更靈活和省事,可是要注意的是,變量延遲是在解釋語塊以後進行,因此這裏的%com%不能使用變量延遲。

set /a \test1=123,test2=234

(@echo off

for /f "tokens=1* delims==" %%a in ('set\') do echo %%b

)|sort

::sort對for命令的輸出進行排序,那個@echo off並不是多餘,由於通道以前的如果語塊(for、if或者被成對括號包起來的語句),該語塊中的內容將會以cmd /c的形式運行,此時的回顯是打開的,而變量延遲則是默認關閉的。

dir /ad 123\&&md234||rd 345&tree /f|more

::當存在123文件夾時,建立234文件夾,不然刪除345文件夾,不管結果如何,接下來都會逐屏顯示當前目錄樹。重點是管道命令、邏輯鏈接符的靈活運用

二、句柄的妙用

@echo off 2>nul 3>nul

這個命令不存在...

echo 錯誤回顯呢?

pause

::句柄備份,可用於屏蔽全部正確或錯誤回顯

cd.>1.txt 2>2.txt 3>3.txt 4>4.txt 5>5.txt 6>6.txt 7>7.txt 8>8.txt 9>9.txt

::用一個命令建立9個文件,效率天然提升了

@echo off

(for /r %%a in (*.*) do del /f /s "%%~nxa" 3>>"%%a") 2>nul 4>>%0

pause

::利用寫入句柄會佔用文件的特性實現高效刪除重複文件

待續...

出處:http://www.uzzf.com/news/1930.html

相關文章
相關標籤/搜索