iT邦幫忙

0

DOS批次檔同時執行多個壓縮

請教會寫批次檔高手,小弟有個自動備份壓縮的批次檔想要執行,希望達到的條件有下面三點:

  1. 指定的磁碟機下,依照目錄名稱產生各別壓縮檔(不用管目錄下的子目錄)。
  2. 呼叫7Zip用最大壓縮比與多執行緒。
  3. 可以控制同時進行壓縮的動作,例如保持五個壓縮動作進行。這個舉一個例子,例如磁碟機下共有100個資料夾,批次檔在運作的時候一直保持同時進行五個目錄壓縮的動作,直到100個資料夾全部被壓縮完畢(當然到最後會越來越少,因為已經沒有需要壓縮的資料夾)。

目前程式遇到問題

  1. 目錄名稱中間有一個或多個空格。
  2. 找不到方式可以同時讓7Zip進行壓縮的動作。
  3. 也找不到方式讓程式可以保持控制五個壓縮動作的方式。

目前批次檔內容
@Echo Off

Set PathD=D:\Data
Set LogD=E:\Log\

For /F "Tokens=1-4 Delims=/ " %%a IN ("%Date%") Do (
Set LogDate=%%a%%b%%c
Set LogF=Data_%%a-%%b-%%c.log
)

T:
Del /f /s /q T:*._mp
Del /f /s /q T:\Thumbs.db

For /f "Tokens=* Delims=." %%I IN ('Dir /b') DO (
"C:\Program Files\7-Zip\7z.exe" -tZip -Mx9 -mmt a %Pathd%%LogDate%"%%I.zip" "T:%%I*" >> %LogD%%LogF%
timeout /t 10
)
E:

Daniel iT邦新手 2 級 ‧ 2018-07-21 18:25:37 檢舉
不知道 start 指令能不能幫你,試試看。
不過既然批次檔的本質是一條一條的指令依序執行,不支援你說的多工和監控數量好像也蠻正常的。
Start 的指令有測試過,網路上找到的文章是透過呼叫 CMD 跑另外的指令,但這個我遇到的問題有兩個。
1. 因為 7Zip 呼叫的參數跟命令沒辦法這樣用,太多空格。
2. 主程式沒辦法控制呼叫的數量,會無限制開下去。
蟹老闆 iT邦大師 1 級 ‧ 2018-07-24 09:10:33 檢舉
這裡是不是少了個 " 號 a "%Pathd% 而這裡是不是多了個 " 號%LogDate% "%%I.zip
"C:\Program Files\7-Zip\7z.exe" -tZip -Mx9 -mmt a %Pathd%%LogDate%"%%I.zip" "T:%%I*" >> %LogD%%LogF%

1 個回答

1
蟹老闆
iT邦大師 1 級 ‧ 2018-07-24 11:58:46
最佳解答

請參考
如要修改同時執行的數量請修改 Set Thread=3 <-同時執行的數量

@Echo OFF
Title Pseudo Daemon .......
SetLocal ENABLEDELAYEDEXPANSION
Set Thread=3
Set Current=0
Set Files=0
(For /f %%i In ('dir /ad /b "%~pd0"') Do (
	Set /a FileTotal += 1	
	Set FileTotal!FileTotal!="%~pd0%%i"
))||(Echo 需要有資料夾&Pause&Exit)
:Start
Cls
Echo Files = !Files! / %FileTotal%
Echo.    工作階段	 PID	    記憶體用量
For /f "eol=資 skip=1 tokens=2-5" %%a In ('TaskList /NH /FI "WINDOWTITLE eq %Thread%Thread"') do (
	Echo. 	%%c	%%a		%%d   			
	Set /a Current =!Current!+1
)
IF !Current! GEQ %Thread% (
	TimeOut /T 1
	Set Current=0
	Goto :Start
)
::這裡用來放要執行的命令,將 "timeout /t 5" 修改成要執行的命令
Start /Min "%Thread%Thread" "%SystemRoot%\system32\cmd.exe" /c "timeout /t 5"
Set /a Files = !Files!+1
If !Files! GTR !FileTotal! Goto :EOF
Goto :Start
看更多先前的回應...收起先前的回應...

非常謝謝IT邦大師蟹老闆。

這邊可以再請教一下您提供的方式嗎?

  1. 第一個 For 迴圈是計算出總共有多少資料夾的數量,應該沒錯吧?
  2. 後面執行"TimeOut /t 5"的這一部份,如果我是要以資料夾名稱做為壓縮檔案名稱與來源,我可以使用哪一個變數?

謝謝您。

蟹老闆 iT邦大師 1 級 ‧ 2018-07-25 09:00:20 檢舉

1.除了計算數量外也會將目錄名稱加到變數中,以便後續使用
2.如果要取得資料夾名稱(含路徑)可以使用 !FileTotal%Files%!
這個變數(FileTotal)命名錯誤,且沒有先賦值會造成一些問題,所以有做了一些修改,修改後取得資料夾名稱(含路徑)使用 !Dir%Files%!

@Echo OFF
Title Pseudo Daemon .......
SetLocal ENABLEDELAYEDEXPANSION
Set Thread=3
Set Current=0
Set Files=0
Set FileTotal=0
(For /f %%i In ('dir /ad /b "%~pd0"') Do (
	Set Dir!FileTotal!="%~pd0%%i"
	Set /a FileTotal += 1
))||(Echo 需要有資料夾&Pause&Exit)
:Start
Cls
Echo Files = !Files! / %FileTotal%
Echo.    工作階段	 PID	    記憶體用量
For /f "eol=資 skip=1 tokens=2-5" %%a In ('TaskList /NH /FI "WINDOWTITLE eq %Thread%Thread"') do (
	Echo. 	%%c	%%a		%%d   			
	Set /a Current =!Current!+1
)
IF !Current! GEQ %Thread% (
	TimeOut /T 1
	Set Current=0
	Goto :Start
)
::這裡用來放要執行的命令,將 "timeout /t 5" 修改成要執行的命令
Start "%Thread%Thread" "%SystemRoot%\system32\cmd.exe" /c "timeout /t 5"
Set /a Files = !Files!+1
If Not !Files! LSS !FileTotal! Goto :EOF
Goto :Start

增加了:
Set FileTotal=0
修改了:
Set Dir!FileTotal!="%~pd0%%i"
If Not !Files! LSS !FileTotal! Goto :EOF

謝謝的 IT邦大師蟹老闆 回覆
不過這邊測試有遇到幾個問題,想與您討論一下

  1. 我只是在下述這一行修改了 "%Thread%Thread" 這個變成 "%Thread%:Thread",程式就會變成一口氣執行了所有資料夾數量(比方說有10個目錄就執行10個視窗),這是為什麼?
    Start "%Thread%:Thread" "%SystemRoot%\system32\cmd.exe" /c "timeout /t 60"

  2. 是可以取得資料夾路徑與資料夾名稱,但是只要資料夾有空格就無法取得完整的資料夾名稱。例如小弟進行測試的時候,新增了10個資料夾名稱(New folder、New folder (2)、New folder (3)....以此類推),但是在執行的時候只能看到取得的資料夾名稱只有New,不是New folder這個名稱。

  3. 如果不需要路徑,只要完整的資料夾名稱,可以怎麼修改?

謝謝您!!

蟹老闆 iT邦大師 1 級 ‧ 2018-07-26 10:31:38 檢舉

1.這個"%Thread%Thread"是用於計算視窗數量的指標,如果修改則須一併修改

For /f "eol=資 skip=1 tokens=2-5" %%a In ('TaskList /NH /FI "WINDOWTITLE eq %Thread%Thread"')....

中的 %Thread%Thread
2.如果要取用變數需加上""將變數包起來,若僅是ECHO 印出變數則可無""
3.使用這個語法 "!Dir%Files%!"
更新:
3誤解了,請將Set Dir!FileTotal!="%~pd0%%i"修改成Set Dir!FileTotal!="%%i"

感謝 IT邦大師蟹老闆 回覆
這邊提供測試環境的畫面,如圖樣子,資料夾的名稱有可能存在多個空格
https://ithelp.ithome.com.tw/upload/images/20180726/20006167grXYgwqDL8.jpg

程式如您提供的,我有修改一小部分
Start "%Thread%Thread" "%SystemRoot%\system32\cmd.exe" /k "Echo !Dir%Files%!"

程式執行的結果,可以看到取得的資料夾名稱僅有開頭的"New"而已
https://ithelp.ithome.com.tw/upload/images/20180726/20006167JOpUfur1Tl.jpg

請問這樣子有辦法解決嗎?

蟹老闆 iT邦大師 1 級 ‧ 2018-07-27 00:24:31 檢舉

疏忽了!
請在(For /f %%i In ('dir /ad /b "%~pd0"') Do ....加上這個參數 "tokens=*" 即可For /f "tokens=*" %%i In ('dir /ad /b "%~pd0"') Do (

感謝 IT邦大師蟹老闆,測試已經可以正常使用了
非常謝謝您這麼熱心提供協助!!

這邊提供修改後的多執行緒方式壓縮備份資料夾批次檔(7Zip)

@Echo OFF
Title Pseudo Daemon .......
SetLocal ENABLEDELAYEDEXPANSION

Set Thread=3
Set Current=0
Set Files=0
Set FileTotal=0

(For /f "tokens=*" %%i In ('dir /ad /b "%~pd0"') Do (
	Set Dir!FileTotal!="%%i"
	Set /a FileTotal += 1
))||(Echo 需要有資料夾 && Pause && Exit)

:Start
Cls
Echo Files = !Files! / %FileTotal%
Echo.    工作階段	 PID	    記憶體用量
For /f "eol=資 skip=1 tokens=2-5" %%a In ('TaskList /NH /FI "WINDOWTITLE eq %Thread%Thread"') do (
	Echo. 	%%c	%%a		%%d   			
	Set /a Current =!Current!+1
)
IF !Current! GEQ %Thread% (
	TimeOut /T 5
	Set Current=0
	Goto :Start
)

::這裡用來放要執行的命令,將 "timeout /t 5" 修改成要執行的命令
Start "%Thread%Thread" "%SystemRoot%\system32\cmd.exe" /c "C:\PROGRA~1\7-zip\7z.exe -Mx9 -mmt -tZip a !Dir%Files%!.zip !Dir%Files%!"
Set /a Files = !Files!+1
If Not !Files! LSS !FileTotal! Goto :EOF
Goto :Start
蟹老闆 iT邦大師 1 級 ‧ 2018-07-27 09:14:19 檢舉

/images/emoticon/emoticon12.gif

我要發表回答

立即登入回答