今天想利用 BAT 檔來完成 檔案的複製工作,

像是,定期備份桌面的檔案之類的阿~

按下去就自動跑好多棒啊!

 

製作批次檔其實不難,1. 打在 txt 裡,2. 另存成 .bat 檔,就完成了。

麻煩是麻煩在語法不知道如何使用阿!! XD

於是就查了查 DOS 批次檔語法~


 

解釋一下:

BAT 是 Batch 的簡寫,因此 Batch Language 就是批次檔所使用的語法喔!

DOS 是 Microsoft 的命令提示字元 (cmd),也就是背景一團黑的那個啦XP

換句話說,這邊的指令只適用 Windows 喔 MacOS 的 terminal 指令是不一樣的~

以下直接以實例來講解,講解部分也很精簡,自己試過揣摩看看應該就能理解啦~

 

範例1:

@ECHO OFF

CD C:\Program Files (x86)\Google\Chrome

PAUSE

REM 複製到D:\底下~~~

COPY  *.txt  D:\David\備份BA~1\電腦\Chrome

ECHO finish

 

第一行打 "ECHO OFF",這樣一來之後的命令都不會顯示,改成 "ECHO ON" 的話,每行輸入的命令就都會出現在螢幕上~

第二行 CD <路徑> 就是前往那個路徑,這是基本的 DOS 語法(不知道請見下面連結)

第三行 PAUSE 會暫停,cmd 視窗就會停住等你按任意鍵繼續

第四行 REM 是註解用的 (remark),DOS 會略過此行

第五行 COPY  *.txt  <路徑>,是複製所有 txt 結尾的檔案,到路徑目標資料夾那裡( *是萬用字元,也是基本 DOS 語法喔xD)

第六行 ECHO finish,會在螢幕上顯示 ECHO 後面的字串,所以就會顯示 "finish"

 

第五行注意:

       COPY  *.txt   D:\David\備份BA~1\電腦\Chrome

它的路徑原本是 " D:\小David\備份 Backups\電腦\Chrome "

但是因為 "備份 Backups" 這個檔名裡面含有空格,DOS 無法接受,所以需要轉換成 8.3 format,

轉換方法是在某個目錄底下打 "dir/x",就會以 8.3 的格式列出目錄底下的檔名了~

 

 


常用 DOS 語法:https://mrtang.tw/blog/post/9751934 (有提到萬用字元 * )

https://mrtang.tw/blog/post/9848241 (講解CD, MD, RD, DIR)

https://mrtang.tw/blog/post/10779313 (講解REN, TYPE, ATTRIB)

BAT 批次檔語法:http://33tsai.blogspot.tw/2008/04/bat.html

               上面是第一頁,第二頁在這邊:http://33tsai.blogspot.tw/2008/04/bat_21.html ,此篇文主要都是參考這兩篇的喔~

檔名轉換成 DOS 8.3 格式:http://goo.gl/oEsDCh 

               裡面就有提到 "dir/x" 的方法~


 

 

範例2:

@ECHO OFF

IF "%1"=="A" ECHO Apple

IF "%1"=="B" ECHO Boy

輸入:C:\sp.bat  A

輸出:Apple

 

假設這個程式叫做 "sp",並且放在 C:\ 底下,

那麼,當我們在cmd 輸入 "C:\sp.bat  A" 時,參數 "A" 就會被讀到 %1 裡面,於是程式最後就印出了 "Apple"

補充一點:最多可以傳送九個參數喔,%1 ~ %9

 

範例3:

@ECHO OFF 

CD D:\David\備份BA~1\電腦\Chrome\

IF EXIST %1 GOTO PrintFile

GOTO FileNotExist

:PrintFile

    TYPE %1

    GOTO End

:FileNotExist

    ECHO File Not Exist!

    GOTO End

:End

輸入:C:\test.bat  list.txt

輸出:< list.txt  檔案裡的內容 >

 

假設這個程式叫做 "test.bat",並且 "D:\David\備份BA~1\電腦\Chrome\" 底下有放一個叫 "list.txt" 的檔案,

那麼當輸入上面那一串內容時,就會把 txt 裡面內容都印出來。而若找不到此一檔案名稱,就會印出 "File Not Exist!"

補充一點:BAT 程式裡,所有的 "%1" 都是會被輸入參數直接取代掉的喔~

 

第三行,IF EXIST <路徑> <檔名> <動作> ;路徑如果是同個資料夾就可以忽略;其實也可以改成 IF NOT EXIST <.....>

第三行,GOTO PrintFile,效果是直接跳到第五行 ":PrintFile" 那裡執行,也就是說中間的都會略過不執行;標籤的名字可以隨便取,像是 "ABC_NAME001" 等等

第四行,如果第三行沒有跳走的話,就會 GOTO 跳到 FileNotExist

第五~七行,是 PrintFile 所要執行的內容;TYPE <檔名> 會把那個檔案印出來,eg. TYPE list.txt

第七行,執行完記得要再 GOTO 到底下的 :End,否則它會繼續往下執行第八行、第九行喔!

第八~十行,是 FileNotExist 所要執行的內容

 

 


2016/08/06  更新:

終於了解了 FOR 的用法,以及其他變數的用法了!

可以前往底下這個連結:(如果不排斥英文的話XD)

Batch File Commands  (網站關了QQ 找不到文章惹,寫的不錯的說...)

(但沒關係,推薦另一篇也很豐富的教學網站:Guide to Windows Batch Scripting )

如果還是需要中文講解,

就在我這篇底下留個言吧~ 我再幫忙解惑~

 

 


2017/07/26 更新:

補充幾篇連結:

命令提示字元 19:迴圈進階   如果你覺得上面的介紹還太粗淺了,這裡有更詳細 FOR 功能解析!

Set - Environment Variable   這個是以 SET 為例,它有最詳盡的功能說明。(應該說它就是說明書,最詳盡但未必好懂就是了) 你可以在搜尋框框打任何想查詢的其他指令喔!

 

除了以上兩個資源頗豐的連結外,以下是我個人另外找到的零碎資料:  (雖然目前只找到一個的樣子XD)

Q1: Batch 如何用正規表示式(regex) 來篩選特定的字串呢?

A1: 使用 findstr /r  (也可搭配 errorlevel)

你可以來實驗看看以下這段,之後再試著把var 改成 dbcefg 看看有何不同,最後再試著把第二行框框裡的改成 [a-z]

set var=abcefg

echo %var% | findstr /r "^[a-c]">nul

if errorlevel 1 (echo no) else (echo yes)

第一行就是簡單的設定變數,將var 設定成那串字

第二行首先,就是先把var 給印出來(記得,變數取用時需要在前後都加上%

但是後面有個 "|",是重新導向的意思,所以原本要印到螢幕上的字,就丟給了後面的 findstr 處理。

"^[a-c]" 意思是以 a~c 字母開頭者,像是 ^[a-zA-Z0-9],就相當於尋找所有的英文及數字開頭者。(詳情請google正規表示式)

最後的 ">" 也是重新導向的意思,丟給nul 的目的是讓它不要顯示出來。你可以試試看把 ">nul" 拿掉,結果就會被印到螢幕上了。

第三行是依據 errorlevel 的值,來決定要顯示 yes or no。原理是這樣的:任何指令都會有回傳值,照理說如果正確執行了,就會回傳 0,若失敗了就不是 0。

而errorlevel 會保存上一行指令的最終回傳值,因此若 findstr 有成功找到,則回傳值為 0,反之則大於 0  (Guide to Windows Batch Scripting 這篇的 Part3 有些說明)

 

 


2018/09/14 更新:

真不好意思,連結居然破掉了!! > <

下次連結如果破掉,還請大家幫忙跟我說一聲喔!

 

 

文章標籤
創作者介紹
創作者 Davidhu127 的頭像
Davidhu127

I Stand Up For Myself

Davidhu127 發表在 痞客邦 留言(5) 人氣()


留言列表 (5)

發表留言
  • abc
  • 哈囉 想問我現在有個bat檔她開啟時都是在某個資料夾內部的檔案
    ECHO off
    set PATH=%CD%\MinGW\bin:%PATH%
    "%CD%\MinGW\msys\1.0\msys.bat"

    我想把它改成開啟以後路經在我桌面上該怎麼改?
    c:\users\g552\desktop
    謝謝!!
  • 你好,不好意思忘記回覆你的留言了><
    你是指說,這個 bat 檔開啟時的路徑(%CD%)都是在某個資料夾內部,
    但你希望路徑改成在桌面,是這個意思嗎?

    如果是這樣,那你只需要加上這一行就可以了喔~ CD C:\users\g552\desktop

    Davidhu127 於 2017/01/26 16:23 回覆

  • 白馬王
  • 感謝您的教學,很仔細,可以幫助大家更好喔!
  • 嗯嗯!一起讓世界成為更好的地方吧~

    Davidhu127 於 2017/01/26 16:09 回覆

  • Hughes
  • 非常實用!!謝謝分享!!
  • 謝謝你的肯定!

    Davidhu127 於 2017/02/26 23:05 回覆

  • 志明 陳
  • 請問一下批次檔有辦法執行去複製A.txt裡帶著ABC的文字.到另一個B.txt裡嗎?
  • 當然可以喔!
    宏觀上來看,首先你要將 A.txt 裡每一行字個別讀取出來,所以會需要用到FOR。接下來,你想對每一行字做檢查,看是否含有特定的文字片段,所以會需要常規表示式(regex)。
    以下為參考code:

    @ echo off
    for /f %%L in (A.txt) do (
     echo %%L | findstr /r "ABC" >> b.txt
    )

    Davidhu127 於 2017/07/27 06:42 回覆

  • 訪客
  • 想請問您,批次檔是否能做到將檔名大寫改小寫的部分,網上找各種資料都無法達到目的..
  • https://stackoverflow.com/questions/34713621/batch-converting-variable-to-uppercase
    推薦他解答的第二種方法 (使用WSH)
    我仿照他,寫了以下code,它會把當前位置的所有txt檔名轉成大寫,然後印出來給你看
    (記得把 @ 改成半形喔)

    @if (@CodeSection == @Batch) @then
    @echo off & setlocal

    rem # For each txt file
    for %%F in (*.txt) do (
      rem # Change to uppercase and print it out
      for /f "delims=" %%I in ('cscript /nologo /e:JScript "%~f0" "%%F"') do (
        echo %%~I
      )
    )
    goto :EOF
    @end
    WSH.Echo(WSH.Arguments(0).toUpperCase());

    Davidhu127 於 2018/09/14 13:44 回覆