如果你問一個對批處理不太熟悉的程式設計師它的主要用途,他們的回答可能會提到移動檔案。批處理可以做更多的事情,但毫無疑問,它的主要用途之一是檔案移動。在本文中,我們將探索不同的命令和可用的技術。您還將瞭解如何建立空檔案,以及合併、移動、重新命名和刪除檔案的方法。我將介紹檔案掩碼和萬用字元,允許您在許多類似命名的檔案上執行命令,而不僅僅是一個。
檔案複製命令
批處理有三個用於複製檔案的命令:copy
、xcopy
和robocopy
。在本節中,我將對它們進行比較,並就何時使用它們給出建議,因為它們都有各自的應用場景。您正在複製許多小檔案還是幾個大檔案?網路穩定嗎?速度是一個考慮因素嗎?您想要一個直接的返回程式碼還是一個更微妙的返回程式碼?日誌對你有多重要?在為任何特定副本決定最佳命令和選項之前,您需要回答許多問題。
copy
copy命令提供了一種快速簡便的方法來建立空檔案:
copy nul D:\Batch\EmptyFile.dat
在批處理中,單詞null表示永遠為空或為空的檔案。這裡,我們複製null檔案來生成一個空檔案,檔案的路徑和名稱由我們選擇。一個有趣的事實:Windows不允許您在任何資料夾中建立名為nul的檔案,即使是手動建立也不行。快去試試吧。
我使用copy命令的唯一其他用途是合併兩個或多個相對較小的檔案。/B選項執行二進位制檔案複製,這意味著每個位元組,甚至是特殊字元,如回車和換行,都被不加更改地複製,從而導致檔案的真正連線。原始檔以加號分隔,後面跟著合併後的檔案:
copy /B D:\Batch\07\Header.txt + D:\Batch\07\Details.txt D:\Batch\07\MergedFile.txt
我們在這裡連線兩個檔案,但是我們可以用更多的加號分隔符合並更多的檔案。
您可能已經注意到,我只提到了copy命令的兩種用法,這兩種用法都不涉及複製實際檔案。您可以使用該命令來複制檔案,但我從不將其用於此目的,因為它很原始,而且選項很少。這些缺點在批處理的第一個版本釋出後不久就顯現出來了,它很快就被更有用和可配置的xcopy命令所取代。
xcopy
xcopy
命令的基本語法有兩個引數——原始檔和目標路徑:
xcopy D:\Batch\07\Source\FileCopy.txt D:\Batch\07\Target\
xcopy
命令的一個巨大優點是,如果目標目錄還不存在,它將建立目標目錄。相反,copy命令找不到路徑,會提示覆制失敗。
在前面的示例中,只給出了目標路徑,這意味著複製的檔案將具有與原始檔相同的名稱。但是我們可以將目標檔案重新命名為xcopy命令的一部分,只需給它一個檔名:
xcopy D:\Batch\07\Source\FileCopy.txt D:\Batch\07\Target\RenameFileCopy.txt
這個命令有時會失敗,因為直譯器不確定目標是一個目錄還是一個檔案(在後面的文章中,我們再一起來討論如何讓該命令一直有效)。
xcopy
命令有兩個選項,我幾乎每次呼叫該命令時都會使用這兩個選項。/Y選項抑制確認覆蓋目標檔案的提示。雖然在透過命令提示符或互動方式執行時請求確認可能是有意義的,但在大多數其他情況下,它只會停止處理並建立掛起,因此最好將其關閉。(強制覆蓋)。
另一個我不能沒有的選項是/F。它顯示覆制的每個檔案的完整源路徑和目標路徑以及檔名,當使用萬用字元複製多個檔案時,這會留下有用的審計跟蹤。如果沒有/F選項,則只顯示原始檔或多個檔案以及總檔案數。在另一種極端情況下,如果你對所有這些資訊不感興趣,你可以使用/Q選項(靜音模式)來關閉顯示器。
使用這兩個不可或缺的選項,下面的命令將取消提示並提供詳細的日誌記錄:
xcopy D:\Batch\07\Source\FileCopy.txt D:\Batch\07\Target\ /Y /F
這個命令有太多可用的選項;使用help命令獲取完整列表。然而,作為一個小的案例,/U
選項只複製目標中已經存在的檔案;/S
選項複製資料夾和子資料夾;/J
選項使用無緩衝的I/O,這對於非常大的檔案是最優的。
D:\Batch\07>xcopy /?
複製檔案和目錄樹。
XCOPY source [destination] [/A | /M] [/D[:date]] [/P] [/S [/E]] [/V] [/W]
[/C] [/I] [/-I] [/Q] [/F] [/L] [/G] [/H] [/R] [/T]
[/U] [/K] [/N] [/O] [/X] [/Y] [/-Y] [/Z] [/B] [/J]
[/EXCLUDE:file1[+file2][+file3]...] [/COMPRESS]
source 指定要複製的檔案。
destination 指定新檔案的位置和/或名稱。
/A 僅複製具有存檔屬性集的檔案,
不會更改屬性。
/M 僅複製具有存檔屬性集的檔案,
關閉存檔屬性。
/D:m-d-y 複製指定日期或之後更改的檔案。
如果未提供日期,僅複製其源時間
比目標時間晚的檔案。
/EXCLUDE:file1[+file2][+file3]...
指定包含字串的檔案列表。每個字串
應在檔案中單獨一行中顯示。當有任何
字串與要複製的檔案的絕對路徑的任何部分
匹配時,將從複製中排除該檔案。
如果指定 \obj\ 或 .obj 之類的字串,將分別
排除 obj 目錄下的所有檔案或具有 .obj 副檔名的
所有檔案。
/P 在建立每個目標檔案之前提示你。
/S 複製目錄和子目錄(空目錄除外)。
/E 複製目錄和子目錄(包括空目錄)。
與 /S /E 相同。可用於修改 /T。
/V 驗證每個新檔案的大小。
/W 提示你在複製前按一個鍵。
/C 即使發生錯誤,也繼續複製。
/I 如果目標不存在並複製多個檔案,
則假定目標必須是目錄。
/-I 如果目標不存在並複製單個指定檔案,
則假定目標必須是檔案。
/Q 在複製時不顯示檔名。
/F 在複製時顯示完整的原始檔名和目標檔名。
/L 顯示要複製的檔案。
/G 允許將加密檔案複製到
不支援加密的目標。
/H 還複製隱藏檔案和系統檔案。
/R 覆蓋只讀檔案。
/T 建立目錄結構,但不復制檔案。不
包括空目錄或子目錄。/T /E 包含
空目錄和子目錄。
/U 僅複製目標中已存在的檔案。
/K 複製屬性。普通 Xcopy 將重置只讀屬性。
/N 使用生成的短名稱複製。
/O 複製檔案所有權和 ACL 資訊。
/X 複製檔案稽核設定(隱含 /O)。
/Y 禁止提示確認是否要覆蓋
現有目標檔案。
/-Y 發出提示,要求確認是否要覆蓋
現有目標檔案。
/Z 在可重啟模式下複製聯網檔案。
/B 複製符號連結本身與連結的目標。
/J 使用未緩衝的 I/O 進行復制。建議用於非常大的檔案。
/COMPRESS 在檔案傳輸期間請求網路壓縮
(如適用)。
/SPARSE 複製稀疏檔案時保留稀疏狀態。
可在 COPYCMD 環境變數中預設開關 /Y。
可在命令列上使用 /-Y 重寫該項。
雖然copy已經被xcopy取代了,但是從技術上講,微軟認為xcopy本身已經被替換為更新的robocopy命令。即便如此,xcopy命令的廣泛使用意味著它仍然可以在可預見的作業系統中使用,我將很快詳細說明,在許多情況下,它仍然是更好的選擇。
robocopy
robocopy實際上代表的是robust copy
,這不是誇張。雖然xcopy有許多有用的選項,但robocopy提供了一些令人印象深刻的日誌記錄和一系列令人難以置信的選項。
儘管robocopy命令比xcopy強大得多,但它也很容易使用。引數有點不同:首先提供不帶檔名的源目錄,然後是目標目錄,最後是要複製的一個或幾個檔案或檔案掩碼:
robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ FileCopy.txt
這個例子在功能上等同於上一節中的xcopy命令,並複製在這裡:
xcopy D:\Batch\07\Source\FileCopy.txt D:\Batch\07\Target\
因為robocopy命令的前兩個引數已知是路徑,所以可以省略末尾的斜槓,這比xcopy有很大的優勢,在xcopy中,若將最後的斜槓遺漏的化,將導致目標目錄轉換為檔名。
robocopy 日誌
要了解robocopy到底有多強大,只需看看它的日誌記錄功能即可。如果你是一名xcopy的愛好者,請先坐好再看前面。冗長是我腦海中浮現的唯一一個詞,即便是這個詞也不夠。除了複製的檔案列表之外,日誌還包括一個花哨的頭、開始和結束時間、檔案大小、複製速度統計、源和目標路徑、複製和跳過的檔案和目錄的總數、以及任何失敗的複製、使用的命令列選項列表,等等。為了提高可讀性,它甚至還使用了大量的空白進行了很好的格式化。
前面展示的簡單robocopy命令複製單個檔案會生成以下日誌:
D:\Batch\07>robocopy Source\ Target\ FileCopy.txt
-------------------------------------------------------------------------------
ROBOCOPY :: Windows 的可靠檔案複製
-------------------------------------------------------------------------------
開始時間: 2024年9月9日 07:04:42
源: D:\Batch\07\Source\
目標: D:\Batch\07\Target\
檔案: FileCopy.txt
選項: /DCOPY:DA /COPY:DAT /R:1000000 /W:30
------------------------------------------------------------------------------
1 D:\Batch\07\Source\
新檔案 0 FileCopy.txt
------------------------------------------------------------------------------
總數 複製 跳過 不匹配 失敗 其他
目錄: 1 0 1 0 0 0
檔案: 1 1 0 0 0 0
位元組: 0 0 0 0 0 0
時間: 0:00:00 0:00:00 0:00:00 0:00:00
已結束: 2024年9月9日 07:04:42
有些結果是不言自明的,如Total、replicated和FAILED,但其他結果則不然。如果要複製的檔案已經在目標路徑中並且是相同的,robocopy足夠聰明,不會浪費時間覆蓋它,而是認為它可以合理地跳過。當由於原始檔和目標資料夾(或原始檔夾和目標檔案)具有相同的名稱而阻止複製時,就會發生不匹配。附加檔案是不在源但已經在目標的檔案和目錄。顯然,這些檔案沒有被複制,但直譯器覺得有義務注意到它們的存在。對於這種複製一個小檔案的任務,日誌記錄可能是多餘的。更有趣的任務可能會繼續執行頁面,但是對於更有趣的任務,日誌記錄可能是無價的。
預設情況下,所有這些資訊都被寫入控制檯(在後續的文章中,我將討論如何將日誌記錄從任何命令甚至整個bat檔案重定向到日誌檔案)。但是robocopy命令的獨特之處在於,您可以使用選項輕鬆建立日誌檔案。日誌檔案的路徑和名稱只跟隨適當命名的/LOG選項,用冒號分隔。
這可能是您第一次看到一個選項在斜槓後面有多個字元,而這個命令有更多的字元。向選項/LOG+新增加號會導致資訊被附加到日誌檔案中,如果它已經存在的話。為了證明這一點,請考慮以下幾點:
set roboLog=D:\Batch\07\Robocopy.log
robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ FileCopy.txt /LOG:%roboLog% /NP
robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ AnotherFileCopy.txt /LOG+:%roboLog% /NP
在將roboLog定義為日誌檔案的路徑和名稱之後,將在兩個robocopy命令中使用它。第一個命令使用其複製中的資訊建立日誌檔案,如果存在的話覆蓋現有檔案,第二個robocopy命令將其複製的結果追加到該日誌檔案中。
最後兩個命令都使用/NP
選項,它代表無進度,因為我認為在建立日誌檔案時必須使用它。如果將資訊寫入控制檯,則每個複製的進度以百分比形式實時顯示,每秒更新多次。在最終顯示100%之前,相對較大的檔案可能會顯示幾十個值。在控制檯中檢視時,這種狀態非常好,但在日誌檔案中,每次更新都會變成一條新記錄。不需要很多大檔案就可以把日誌變成一團亂麻。即使是小檔案也可能導致日誌檔案中出現一些額外的不需要的記錄。/NP
選項很好地解決了這個問題,只在每次複製完成後更新日誌。
有用的robocopy選項
robocopy有許多複製選項,所以我將快速地介紹最有用的選項。但首先,這裡有一個命令作為選項的基礎:
robocopy D:\Batch\07\Source\ D:\Batch\07\Target\
這個簡單的命令(缺少檔案的第三個引數)將源目錄中的所有檔案複製到目標目錄。
該命令自動執行失敗副本的重試,這非常棒,但是預設的重試次數是驚人的100萬次,每次嘗試間隔30秒等待。這可能會導致一個有致命缺陷的複製延遲幾個月。/R
和/W
選項分別覆蓋預設的重試次數和以秒為單位的等待時間:
robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ /R:20 /W:5
使用這些選項,直譯器將重試失敗的副本多達20次,每次嘗試之間間隔5秒,然後啟動中止。選擇對您和您的裝置有意義的值,但不能保留預設值。
如果你新增/S
選項,它也會複製所有的子目錄,除了空的子目錄:
robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ /S
/E
選項複製所有的子目錄,空的和非空的都一樣:
robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ /E
您可以細化此選項,只複製源目錄(D:\Batch\07\Source\)及其直接子目錄中的檔案,而不復制更低階別的子目錄。/LEV
選項定義了級別的數量,包括根節點,為2以處理:
robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ /E /LEV:2
對於非常大的檔案,無緩衝的I/O更有效,並且使用/J
選項呼叫非常奇怪。(這個選項是從xcopy命令借來的,在xcopy命令中已經使用了/U
選項。)/MIN
和/MAX
選項設定要複製的檔案的最小和最大位元組限制。以下兩個命令複製資料夾中的所有檔案,僅對至少1GB的檔案使用無緩衝I/O:
robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ /MIN:1000000000 /J
robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ /MAX:999999999 /MT
我將/MT
選項(它代表多執行緒)隱藏到用於較小檔案的命令中。預設情況下,robocopy命令按順序複製檔案,但該選項並行複製8個檔案。你甚至可以定義執行緒的數量;/MT:128
是最大值,但根據我的經驗,這並不比選項預設值8快多少。我們可以討論閾值,但是對於大檔案的無緩衝I/O和對於小檔案的多執行緒將最佳化任何複製。
/MINAGE
和/MAXAGE
選項定義要根據最後修改日期複製的內容。您可以單獨或一起使用它們來建立日期範圍。以下命令只複製自2000年9月14日微軟災難性地釋出Windows Me以來觸及的檔案,不包括過去7天內更改的任何檔案:
robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ /MAXAGE:20000914 /MINAGE:7
您可以將這兩個選項的值定義為日期(格式為CCYYMMDD)或天數。直譯器足夠聰明,知道這個8位元組的數字表示的是一個日期,而不是超過5萬年的時間跨度。任何少於1900的數字都被直譯器認為是天數。
/PURGE
選項刪除目標中的額外檔案和目錄,顯然您應該謹慎使用,但它是建立備份的一個非常方便的工具。如果有一天你備份了一個資料夾,第二天改變了源目錄中的檔名稱,然後再次備份該資料夾,那麼你最終會在備份中得到一個無關的檔案,除非你使用了/PURGE
選項。更好的是/MIR
選項,它的映象一個目錄樹。/MIR
選項基本上完成了/PURGE
選項的功能,但它包含子目錄。
/XF
選項從副本中排除一個或多個檔案,而/XD
類似地排除一個或多個目錄。/L
選項不復制任何東西;它會生成一個列表,其中包含了如果沒有使用該選項將被複制的所有內容。
您也可以使用robocopy命令來移動檔案。與之前一樣,使用help命令獲取可用選項的完整列表。
robocopy返回碼
xcopy
命令與大多數批處理命令類似,成功執行將返回錯誤級別0,而失敗執行將返回非0的數字。相比之下,robocopy是獨一無二的——如果不理解這種獨特性,就會產生很多困惑。返回程式碼為0表示沒有複製任何內容,但如果至少複製了一個檔案,直譯器將返回1到15(包括1到15)之間的奇數,但即使其中一些程式碼也不完全是好的返回程式碼。下面是robocopy命令生成的六個基本返回程式碼:
- 0 ---> 沒有錯誤,但沒有檔案被複制;換句話說,所有檔案都被跳過了。
- 1 ---> 成功複製一個或多個檔案。
- 2 ---> 發現了一個或多個額外的檔案或目錄;沒有複製。
- 4 ---> 發現一個或多個不匹配;沒有複製。
- 8 ---> 無法複製某些檔案或目錄。
- 16 ---> 沒有任何東西被複制;有一個嚴重的錯誤。
使用程式碼0到5不是更簡單嗎?不,中間的四個程式碼並不是相互排斥的;也就是說,有可能不止一個(甚至四個)同時為真。直譯器將所有為真的程式碼相加,並將總和作為錯誤級別返回。
例如,設想一個將原始檔夾中的所有檔案複製到目標資料夾的robocopy命令,其中一些檔案被成功複製,但目標資料夾也有額外的副本。返回碼1和2都為真;因此,它們的和3作為錯誤級別返回。也有可能在複製檔案時,發現了不匹配的額外內容,並且另一個檔案由於被某人或某些程序開啟而無法複製。計算一下(1 + 2 + 4 + 8),直譯器返回15。
這些返回程式碼為精明的編碼人員提供了微調錯誤處理的機會。返回程式碼1和3顯然是好的,我通常認為3或更少也很好。從4到7的任何值都涉及不匹配,而高於4的任何值至少有一個顯式故障。根據具體情況,不匹配可能是完全可以接受的,因此只有返回程式碼大於等於8才會被認為是錯誤的。
要顯式地驗證至少複製了一個檔案,我們只需要查詢奇數的返回程式碼,我們可以透過後面介紹的的modulo函式來實現。
xcopy vs. robocopy
儘管這個詞帶有主觀色彩,但大多數批處理程式設計師都認為robocopy比xcopy好,因為它有無數的選項、多執行緒、自動重試、令人印象深刻的日誌記錄,以及使其更高效的幕後功能。但有一種主要的bat。當嘗試複製單個檔案時,xcopy錯誤處理到目前為止要好得多。這兩個命令都試圖複製一個不存在的命名檔案:
xcopy D:\Batch\07\Source\NonExistentFile.txt D:\Batch\07\Target\
robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ NonExistentFile.txt
xcopy命令報告沒有複製任何檔案,並返回errorlevel 4,但是robocopy命令返回0,表示沒有錯誤,也沒有複製任何檔案。我認為這應該是一個錯誤。當嘗試複製多個檔案時,當沒有原始檔時,這兩個命令都返回0——這是有意義的,但是這兩個命令都呼叫要複製的顯式檔案,並且robocopy返回程式碼不區分未找到檔案和被跳過的檔案,因為它已經存在於目標目錄中。跳過未更新的檔案是robocopy的一個重要功能,但這與找不到檔案是完全不同的。健壯的日誌使這一點變得清晰,但返回碼卻沒有。
返回碼無法報告檔案未複製(未找到或跳過)的原因,這是一個缺陷,但我們可以克服它。當使用robocopy命令複製一個特定檔案時,可以在errorlevel為0時對目標檔案執行if exist。如果存在,則正確跳過該檔案;如果沒有,則存在錯誤。或者,像我一樣,在這種情況下使用xcopy。
在其他情況下,robocopy命令的複雜返回碼超出了需要的範圍。您可能不關心是否有額外的或不匹配的檔案,而只想要一個簡單的好或壞、零或非零的結果。這並沒有什麼錯,說實話,出於習慣和易用性,我有時仍然會在新程式碼中使用它。
也就是說,正如它的名字所暗示的那樣,robocopy命令要健壯得多。它更具可配置性、速度更快,而且更不容易出錯。如果複製非常大的檔案、大量的檔案,或者由於連線問題而可能失敗的檔案,robocopy是合理的選擇,而且複雜的返回碼有時有一個很大的好處。此外,xcopy命令對路徑和檔名的長度有254位元組的限制。我從來沒有接近超過這個限制,但如果你有,robocopy可以處理它。
關於這個主題,我要做的最明確的宣告是,您永遠不應該使用copy命令來複制檔案,而是將其保留在工具箱中,以便建立空檔案或合併檔案。
檔案模板和萬用字元
前面的所有xcopy示例都複製單個檔案,而robocopy示例要麼複製單個檔案,要麼複製目錄中的所有檔案。但是使用檔案模板和萬用字元,你可以建立更有針對性的命令,只複製目錄中的一些檔案;實際上,它們可能在每次執行時複製不同數量的檔案。檔案模板替換這兩個命令中的檔名,並由一個或多個萬用字元組成,可能包含一些硬編碼文字或解析變數。然後,當它執行時,該命令複製所有滿足或適合該檔案掩碼的檔案。
檔案模板並不是複製檔案的命令所獨有的。本文中即將介紹的移動、刪除甚至重新命名檔案的命令也接受檔案模板來代替檔名,允許你一次移動、刪除和重新命名多個檔案。for命令充分利用了檔案模板,我將在後續中演示如何使用。在檔案上執行某些操作的任何命令都可能使用萬用字元;如果有疑問,可以嘗試一下。
批處理將兩個字元識別為萬用字元,星號(*)和問號(?)。它們的行為完全不同,我將使用xcopy命令詳細說明它們,但首先讓我們看一下要複製的一組檔案。一個非常有條理的人可能會維護包含預算資訊的電子表格,一年中每個月一個檔案。在本演示中,D:\Batch\07\Budget\
資料夾包含電子表格,其命名約定註明年份和月份。這裡有三個例子:
Budget.January2008.xlsx
Budget.February2008.xlsx
Budget.March2008.xlsx
這些檔案來自金融危機和大衰退開始的那一年,資料夾中包含了前後一年類似命名的檔案,以及其他型別的檔案。
星號萬用字元
星號是最常見的批處理萬用字元字元,是零到多個字元的替代品。為了演示,下面的xcopy命令複製2008年以來的所有檔案,或者更具體地說,是D:\Batch\07\Budget\
中滿足Budget.*2008.xlsx
模板的檔案:
xcopy D:\Batch\07\Budget\Budget.*2008.xlsx D:\Batch\07\Target\ /F /Y
星號是萬用字元,表示該命令複製名稱以Budget開頭的每個檔案。以2008.xlsx結尾,中間有一些東西,甚至什麼都沒有。如果一個名為Budget.2008.xlsx的檔案恰好在資料夾中,它也滿足模板,並且是複製的檔案之一。
到年底,應該有12個這樣的檔案滿足這個模板,每個月一個,導致命令複製所有12個檔案。但該命令不會複製2007年或2009年的檔案,也不會複製具有相同名稱但副檔名不同的Word文件,例如Budget.June2008.docx
。如果要從其中一個檔案BudgetAugust2008.xlsx
的名稱中刪除第一個點,直譯器也不會複製它,因為它不滿足模板。
在萬用字元之前插入字母J
的下面非常微妙的變化導致命令只複製三個檔案,分別是一月、六月和七月的檔案:
xcopy D:\Batch\07\Budget\Budget.J*2008.xlsx D:\Batch\07\Target\ /F /Y
在萬用字元前再新增一個字元,Budget.Ju*2008.xlsx
模板將排除一月份的檔案。
您不限於模板中的單個萬用字元。以下是一個使用兩個星號的示例,其中最後一個是副檔名的替換:
xcopy D:\Batch\07\Budget\Budget.*2008.* D:\Batch\07\Target\ /F /Y
前面提到的Word文件Budget.June2008.docx
現在也被命中了。
現在您知道了星號萬用字元可以表示任何長度的任何文字,包括根本沒有文字,但是有時您可能需要更嚴格的限制。批處理有一個鮮為人知的萬用字元,用於此目的。
問號萬用字元
雖然星號是零到多個字元的萬用字元,但問號通常是一個字元的萬用字元。為了只複製帶有四個字元的月份的檔案,我將在原來是星號的地方使用四個問號:
xcopy D:\Batch\07\Budget\Budget.????2008.xlsx D:\Batch\07\Target\ /F /Y
該命令複製6月和7月的檔案,但不復制3月、4月、5月和所有其他月份的檔案,因為這些月份比較冗長。
這看起來很簡單,如果一組或多個問號萬用字元出現在檔案模板的末尾,或者這些問號緊接在一個點之前,批處理還會將空值視為每個問號的有效替換值。
為了說明這一點,我將透過在月份和年份之間插入一個句號來調整檔案命名約定,從而產生如下的檔名:
Budget.April.2008.xlsx
Budget.May.2008.xlsx
Budget.June.2008.xlsx
Budget.July.2008.xlsx
接下來,我將在檔案模板的四個問號和年份之間插入點,如下所示:
xcopy D:\Batch\07\Budget\Budget.????.2008.xlsx D:\Batch\07\Target\ /F /Y
甚至一些有經驗的批處理程式設計師也可能期望6月和7月的檔案只滿足這個掩碼。它們是正確的,因為3月、4月和其他所有用四個以上字母表示的月份的檔案將不會被複制,但5月的檔案也將滿足掩碼。前三個萬用字元匹配May中的三個字母,但第四個問號匹配一個空字元或不存在的字元。即使是名字奇怪的Budget. 2008.xlsx
也滿足這個模板。
結果是,當n個問號萬用字元出現在檔案模板的末尾或後面跟一個點時,模板將滿足0到n個字元。否則,n個問號萬用字元恰好滿足n個字元。這是一個非常微妙的奇怪現象,理解它可能會節省你幾個小時的煩惱。
要注意兩個批處理萬用字元之間的區別,shot、shoot、shut、shunt、shallot甚至sht都滿足sh*t檔案掩碼。在這些詞中,只有shot和shut能滿足檔案模板sh?t
。
短檔名和檔案模板
作為一個更微妙的問題,有時看起來不滿足檔案模板的檔名最終滿足了模板。我們所認為的檔名實際上是一個很長的檔名。預設情況下,Windows還會為計算機上的每個檔案分配一個簡短的檔名。這是舊作業系統中很少使用的遺留,但它仍然存在,當直譯器將檔案與模板進行比較時,它會根據長檔名或短檔名查詢匹配。
短檔名最多八個位元組長,副檔名不超過三個位元組。若恰好命名為NineBytes.Long
的檔名,可能有一個短的檔名如NINEBY~1.LON
。如果嘗試複製副檔名不超過三個位元組的所有檔案,使用*.???
檔案模板,直譯器複製具有四位元組副檔名的檔案,因為它的短檔名滿足掩碼。這個問題不經常出現,但是如果你在一個檔案上得到了意外的命中,檢查它的短檔名。
檔案移動
移動檔案類似於複製檔案;唯一的區別是,檔案被複制後,它存在於兩個地方,而檔案被移動後,原始檔案不再存在。move
命令可以輕鬆地執行此任務。它只是將源和目標作為引數,你通常會看到它帶有/Y
選項,以抑制覆蓋目標的確認提示:(強制移動)
move D:\Batch\07\Source\FileMove.txt D:\Batch\07\Target\ /Y
許多舊程式碼仍然包含move命令,但它在很大程度上已被棄用,取而代之的是robocopy
命令。以下帶有/MOV
選項的命令在功能上等同於前面的move
命令:
robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ FileMove.txt /MOV
從robocopy命令中移動檔名會移動原始檔夾中的所有檔案,但不會移動子資料夾中的任何檔案。
新增/S
選項會移動所有子資料夾中的所有內容,即使需要建立目標子資料夾:
robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ /MOV /S
該命令移動所有檔案。它們不再位於原始檔夾,但原始檔夾結構仍然保留。這是它有點奇怪的地方。我們一直在討論/MOV
選項,它顯然是move的縮寫,但一個類似的命名選項/MOVE
代表……這兩個選項有微妙的不同。帶有/MOVE
選項的robocopy命令真正地移動檔案和目錄。
將E新增到選項後,將在將所有檔案複製到目標後刪除源目錄結構:
robocopy D:\Batch\07\Source\ D:\Batch\07\Target\ /MOVE /S
我們有一個/MOV
選項,它在複製子目錄時移動檔案,還有一個/MOVE
選項,它同時移動檔案和子目錄。它不是特別直觀。
當考慮到使用哪個命令進行特定的移動時,robocopy命令在前面的“xcopy vs robocopy”中提到的所有相同原因的最有效的選擇。但就像xcopy命令一樣,移動命令具有更直接的返回程式碼,而且在批處理生態系統中仍然有一個位置。
檔案刪除
當檔案不再需要時,清理它們是有意義的。del
命令很容易刪除一個或多個檔案。/Q
選項,再次代表安靜模式,防止直譯器請求刪除檔案的許可權。該命令接受要刪除的檔案的多個引數,其中可以使用顯式檔名和檔案模板。下面的命令刪除一個名為Junk.txt
的特定檔案和副檔名為.OLD
的資料夾中的所有檔案:
del /Q D:\Batch\07\Source\Junk.txt D:\Batch\07\Source\*.OLD
使用/A
選項根據檔案的屬性選擇要刪除的檔案。例如,使用/AH
選項只刪除隱藏檔案。相反,/A-H
選項只刪除未隱藏的檔案。與往常一樣,使用help命令獲取完整的選項列表。
透過簡單地使用目錄作為del
命令的引數來刪除資料夾中的所有檔案,但是目錄本身仍然存在。
檔案重新命名
ren
和rename
命令是批處理同義詞;也就是說,它們是同一個命令。第一個引數是要重新命名的檔案,第二個引數是新的檔名:
ren D:\Batch\07\FileRename.txt NewFileName.txt
如果目標檔案已經存在,直譯器返回錯誤級別1。如果有相同名稱的檔案可能已經存在,我會在重新命名之前悄悄地刪除它:
del D:\Batch\07\NewFileName.txt /Q
ren D:\Batch\07\FileRename.txt NewFileName.txt
即使對於這個命令也支援萬用字元,但是我只將ren命令用於顯式檔名,主要是因為該命令不會將重新命名的檔案列表寫入控制檯。
ren命令並不複雜,在兩個引數上都使用路徑是很容易的,但是當您仔細考慮這個問題時,直譯器已經知道了第一個引數的路徑。檔案沒有被移動或複製到任何地方;根據該命令的性質,它被就地重新命名。如果第一個引數沒有路徑,則假定當前目錄,但第二個引數僅為新檔名,並且不應該與之關聯路徑。
總結
如果沒有建立、複製、移動、合併和刪除檔案的能力,批處理就什麼都不是,我在這裡介紹了一組用於這些任務的命令。我討論的一些命令很簡單,但是我討論了不止一個問題以及減輕這些問題的解決方案。您還學習瞭如何使用檔案模板和萬用字元一次在多個檔案上執行這些命令。
複製檔案聽起來似乎是一項簡單的任務,但我詳細介紹了許多可用的技術和注意事項。我希望我向您展示了robocopy命令的強大和有用性,同時也向您灌輸了xcopy命令的簡單性和實用性。
在下一篇文章中,我將描述如何執行用另一種語言編譯的程式,這將涉及到更深層次的討論,即當您沒有提供路徑時,直譯器如何找到要執行的程式。
本文由部落格一文多發平臺 OpenWrite 釋出!