Windows-Server-2008
因為批量讀取文件夾時出現奇怪的行為
我試圖做一個簡單的批處理(這不是全部,但那是讓一切都失敗的部分)
@echo off for /f "tokens=*" %%G in ('dir /s /b /a:d "e:\tmp\*"') do ( echo %%G set fullpath=%%G set basename=%fullpath:~7% echo %fullpath% echo %basename% )
這個腳本應該從任何地方執行,因此有趣的 for 循環。它應該瀏覽目錄,然後做一些事情。
在這個特定目錄中,還有另外 3 個目錄
bomslenovodb
:cpat
和finance
預期輸出
e:\tmp\bomslenovodb e:\tmp\bomslenovodb bomslenovodb e:\tmp\cpat e:\tmp\cpat cpat e:\tmp\finance e:\tmp\finance finance
實際輸出
First run e:\tmp\bomslenovodb ECHO is off. ECHO is off. e:\tmp\bomslenovodb e:\tmp\cpat ECHO is off. ECHO is off. e:\tmp\cpat e:\tmp\finance Second run ECHO is off. ECHO is off. e:\tmp\finance e:\tmp\bomslenovodb e:\tmp\finance ECHO is off. e:\tmp\bomslenovodb e:\tmp\cpat e:\tmp\finance Third run ECHO is off. e:\tmp\cpat e:\tmp\finance e:\tmp\finance ECHO is off. e:\tmp\finance e:\tmp\bomslenovodb e:\tmp\finance e:\tmp\finance Fourth run e:\tmp\bomslenovodb e:\tmp\cpat e:\tmp\finance e:\tmp\finance e:\tmp\cpat e:\tmp\finance e:\tmp\finance e:\tmp\finance e:\tmp\finance
在我看來,它的
set fullpath=%%G
行為不符合預期,因此它的值設置不正確。我在 Windows Server 2008 機器上,有什麼想法嗎?
經典的批處理錯誤:-)
SET 命令工作正常。失敗的是你的擴張。
%VAR%
解析語句時會發生擴展,並且一次解析 FOR 循環中的所有命令。對於任何帶括號的程式碼塊也是如此。因此 和 的值%fullpath%
在%basename%
整個 FOR 循環的執行過程中是恆定的——在進入循環之前存在的值(在這種情況下未定義)。解決方法是使用延遲擴展,它發生在命令執行之前。延遲擴展必須先啟用,
setlocal enableDelayedExpansion
然後才能使用。擴展的語法更改為!VAR!
.@echo off setlocal enableDelayedExpansion for /f "tokens=*" %%G in ('dir /s /b /a:d "e:\tmp\*"') do ( echo %%G set fullpath=%%G set basename=!fullpath:~7! echo !fullpath! echo !basename! )
但仍然存在一個潛在問題。文件名可以包含該
!
字元,並且任何包含的 FOR 變數!
都將在啟用延遲擴展時在擴展時損壞。解決方案是在循環內打開和關閉延遲擴展。@echo off for /f "tokens=*" %%G in ('dir /s /b /a:d "e:\tmp\*"') do ( echo %%G set fullpath=%%G setlocal enableDelayedExpansion set basename=!fullpath:~7! echo !fullpath! echo !basename! endlocal )
如果您需要保護
!
文字,並且您需要變數分配在迭代中保持不變,那麼最簡單的做法是使用 CALLed 過程,以便您可以使用正常擴展。只需將 FOR 變數值傳遞給 CALL 參數。但是使用 CALL 比將所有內容直接放入循環中要慢得多。@echo off for /f "tokens=*" %%G in ('dir /s /b /a:d "e:\tmp\*"') do call :proc "%%G" exit /b :proc echo %~1 set "fullpath=%~1" set "basename=%fullpath:~7%" echo %fullpath% echo %basename% exit /b