iT邦幫忙

1

利用批次檔截取不固定長度字串中的部份字串

公司的電腦使用cobian backup 11 備份資料, 但不幸的是, 備份的資料需要包含主機的資料夾權限, 在win7/win10 會發生部份權限的怪異事件, 也就是某些資料夾竟然無法由 cobian backup 自動刪除 (拒絕存取), 只知道確實是權限安全性造成的, 也找不出原因. 如果是用檔案總管刪除, 是正常可刪除. 所以才想到要做一個批次檔來把 log 記錄中有"無法刪除資料夾" 的資料路徑截取出來, 再用指令去刪除資料夾的構想.

cobain backup的錯誤訊息範例:
ERR 2020-06-29 18:58 無法刪除資料夾『E:\04_資料查詢區\402_ISO 程序書、SOP(品保)\ISO 9001 品質手冊 & 程序書\品保-程序書\程序書』:存取被拒。

很久沒用進階的指令了, 一開始吃了些苦頭, 也上網找了很多範例, 大多是在講語法, 不然就是有人建議用 powersshell, 我也知道 vbs 有更大的彈性, 但在公司也沒太多時間去研究, 於是花了兩個工作天, 做出我要的結果, 其中最燒腦的部份, 就是要在一串不固定長度字串中截取我要的字串, 幸好log還有規則, 方便我作業, 不然就只好真真實實的寫程式了

要在一串不固定長度字串中截取我要的字串
ERR 2020-06-29 18:58 無法刪除資料夾『E:\04_資料查詢區\402_ISO 程序書、SOP(品保)\ISO 9001 品質手冊 & 程序書\品保-程序書\程序書』:存取被拒。
變成
E:\04_資料查詢區\402_ISO 程序書、SOP(品保)\ISO 9001 品質手冊 & 程序書\品保-程序書\程序書

好不容易想通了 for delims 的用途 (年紀大思緒反應果然有差)

幸好log字串還有規則
for /F "tokens=1,2,3 delims=『』" 

在初期測試時一直失敗, 批次檔完全無法正常運作, 花了一些時間找出幾個怪異點,
1.cobian backup 的 log 檔編碼居然是 UTF-16LE, 批次檔無法處理, 難怪系統讀不到資料
解決方式: 使用 ConvertZ 轉成 UTF-8
2.FINDSTR 無法讀取 UTF-8
解決方式: 改用 FIND, 若檔案格式是 ANSI, FINSTR /C:"中文字串.*"

我的工作環境
o.s: win10pro x64 /1909

完整的批次檔, 有需要的人可以參考修改
最後還是要感謝 iT邦幫忙技術問答 提供了我很多參考資料

@echo off
cls

rem ****************************************************************************
rem * 日期: 2020.06.30                                                         
rem * 版本: 1.0                                                                
rem * 設計: goodnight                                                          
rem *                                                                          
rem *                                                                          
rem * 注意事項
rem * findstr 無法存取 utf-8 編碼的檔案
rem * findstr 中文搜尋方式 findstr /c:"字串.*"

rem 顯示UTF-8 CODE
chcp 65001

setlocal
set logfname=
rem log filename
set CBLog=D:\CBLog
rem 要處理的 log 檔資料夾路徑
set runmode=2
rem runmode=2 直接讀取 D:\CBLog 檔案, 不從C:\Program Files (x86)\Cobian Backup 11\Logs複製檔案
rem 

if %runmode%==2 goto start2
rem 先把 log 複製到另一個資料夾, 再轉碼 (utf-16 le -> utf-8)
del /q  %CBLog%
robocopy /np /unilog:CBcopy.txt "C:\Program Files (x86)\Cobian Backup 11\Logs" %CBlog%
I:\ConvertZ\ConvertZ /i:ule /o:utf8 "%CBLog%\*.txt"
rem ConvertZ 是外部程式, 要自行下載
rem ConvertZ 直接複寫原檔 
rem ConvertZ 指令參數參考: [http://fw-william.blogspot.com/2013/12/convertz-command-line.html](http://fw-william.blogspot.com/2013/12/convertz-command-line.html)
          
:Start2          
echo.
echo.
echo (1/4)==== D:\DirList.txt 產生檔案清單 ====
del /q D:\DirList.txt
del /q D:\DelList.txt
dir "%CBLog%\*.txt" /b /on > D:\DirList.txt

echo.
echo.
echo (2/4)==== D:\DelList.txt 無法刪除資料夾清單檔產生中 ====
rem 利用 find.exe(com) 找出有"無法刪除資料夾"的檔案, 一次產生完, 避免使用太多巢狀迴圈, 程序也比較易讀 
for /F "usebackq tokens=* delims=," %%i in (D:\DirList.txt) do (
for /F "usebackq" %%J  in ("%CBLog%\%%i") do (
find "無法刪除資料夾" "%CBLog%\%%i" >> D:\DelList.txt)
)

rem for "tokens=* delims=," : 把一列字串視為一個區段, 分隔符號用 ', ' (這是我的 log 檔規則, 其他 log 必須自行研讀設定, 只要內容沒有 ',' , 也可以用 ',' 做分隔符號

echo.
echo.
echo (3/4)========只取出路徑文字========
del /q RDdir.bat
for /F "usebackq skip=2 tokens=1,2,3 delims=『』" %%i in (D:\DelList.txt) do (
if %%j == "" loop
if %%j == "----------" loop
echo rd /s /q "%%j" >> D:\RDdir.bat )

rem "tokens=1,2,3 delims=『』" : 我所需要的資料格式, 剛好是由 『』包夾, 所以分隔符號用『』, 剛好可以分成三個區塊資料 1=%%i , 2=%%j , 3=%%k, 我只需要『』中間區塊資料, 所以是 %%j

echo.
echo.
echo (4/4)========開始移除資料夾========
Call D:\RDdir.bat

rem 為了安全, 執行完成後刪除, 反正都會自行產生 
DEL /q D:\RDdir.bat

rem 顯示 BIG-5
chcp 950

:end
endlocal
     

尚未有邦友留言

立即登入留言