我詳細解釋了什麼aschipfl寫在他的評論已絕對正確。
這兩個批處理文件也可在Windows 2000和Windows XP上使用,也可使用cmd.exe
作爲命令解釋程序。批處理文件不能在MS-DOS,Windows 95和Windows 98上使用非常有限的command.com
作爲命令解釋程序。
可以在命令提示符窗口中使用參數/?
執行命令以獲取輸出對此命令的幫助。在幫助中寫入並啓用了命令擴展這意味着僅在基於Windows NT的Windows版本上支持cmd.exe
,並且不支持由MS-DOS或Windows 9x使用command.com
。這意味着例如for /F
或if /I
或call :Subroutine
在Windows 9x上或在基於Windows NT的Windows上顯式禁用命令擴展時不可用。在Windows 9x上,甚至不可能使用"%~1"
或"%~nx1"
。
第一個批處理文件執行FOR循環只有1命令恰好1次:
set "dt=%%a"
所有其它命令後FOR循環完成以下被執行。換句話說,第一批處理文件中的循環不使用命令塊在循環內運行多個命令。
只要Windows NT命令解釋器檢測到命令行上的命令塊的開頭,它此命令行上執行的命令在首次使用前處理整個命令塊。
這意味着第二批文件中使用%Variable%
所有變量引用已經膨脹FOR執行該命令之前,並在命令塊中的命令上述所限定FOR命令行然後用變量的值來執行。這可以通過從批處理文件的第一行去除@echo off
或它從一個命令提示窗口內更改爲@echo ON
和運行批處理文件中可以看出,因爲現在可以看出與(
定義的命令行分別整個命令塊... )
是通過命令解釋器預處理後真正執行。
所以每當一個環境變量被定義或命令塊內進行修改並將其值在同一個命令塊引用的,有必要使用延遲擴展或使用的解決方法。
一種解決方法如下所示:
setlocal EnableExtensions DisableDelayedExpansion
set "FolderPath=%SystemRoot%\System32"
for /F "skip=5 tokens=1,2,4 delims= " %%a in ('dir /AD /TC "%FolderPath%\."') do if "%%c"=="." (
set "VarA=%%a"
set "VarB=%%b"
call echo %%VarA%%, %%VarB%%
call set "Day=%%VarA:~0,2%%
call echo %%Day%%
)
endlocal
pause
由於沒有@echo off
在這個批處理代碼可在執行批處理文件,在這裏發生的事情可以看到頂部。在處理命令塊時,每個%%
都被修改爲%
。所執行的是命令行。
call echo %VarA%, %VarB%
call set "Day=%VarA:~0,2%
call echo %Day%
CALL用於處理該行的其餘部分的第二時間與不具有或具有字符串替換可以通過相應的值替換環境變量引用運行ECHO和SET命令的命令。
另一個解決方法以避免延遲擴展使用子程序:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "FolderPath=%SystemRoot%\System32"
for /F "skip=5 tokens=1,2,4 delims= " %%a in ('dir /AD /TC "%FolderPath%\."') do if "%%c"=="." call :ProcessCreationDate "%%a" "%%b"
endlocal
pause
goto :EOF
:ProcessCreationDate
echo %~1, %~2
set "Day=%~1"
set "Day=%Day:~0,2%
echo %Day%
goto :EOF
子程序是例如嵌入當前批處理文件中的另一個批處理文件。
第一goto :EOF
通過的子程序的代碼避免下降。
第二goto :EOF
不會是必要的,如果上述的線是批處理文件的最後一行。但是,儘管如此,仍然建議使用它,以便在後面的更多命令行中像第二個子例程一樣添加。
第二個批處理文件是獲得在其上創建指定的文件夾的一天。可以在不使用延遲擴展和任何解決方法的情況下對此批處理文件進行編碼。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "FolderPath=%SystemRoot%\System32"
for /F "skip=5 tokens=1,2,4 delims= " %%a in ('dir /ad /tc "%FolderPath%\." 2^>nul') do if "%%c"=="." set "CreationDate=%%a, %%b" & goto OutputDateAndDay
echo Failed to get creation date of "%FolderPath%"
endlocal
pause
goto :EOF
:OutputDateAndDay
echo %CreationDate%
set "Day=%CreationDate:~0,2%
echo %Day%
endlocal
pause
一旦與指定的文件夾的創建日期感興趣的行被找到,創建日期/時間被分配到環境變量和FOR退出循環使用命令GOTO繼續執行在下面的標籤上。對於&
運營商的含義見Single line with multiple commands using Windows batch file。
這種解決方案比所有其他方法更好,因爲FOR循環執行與3個命令IF單個命令行,SET和GOTO只有一個時間,這使得該解決方案是最快的。並且,當無法確定目錄的創建日期時,會輸出錯誤消息,因爲該目錄根本不存在。
當然也有可能還添加了GOTO命令的其他解決方案,一旦目錄的創建日期被確定和輸出退出FOR循環。儘管如此,最後的解決方案仍然是最快速並且以我的觀點來看最適合這項任務的解決方案。
順便說一句:所有發佈的批處理文件的例子都在Windows XP上測試過,併產生了預期的輸出。
延遲擴展功能在Windows XP下可用。無論如何,爲了避免它,使用'call echo %% vara %%,%% varb %%'和'call set day = %% vara:〜0.2 %%'這樣的調用語法,或者移動主體循環放入一個[子例程](http://ss64.com/nt/call.html)中,通過'call'調用它作爲[參數]傳遞所有相關值(http:ss64.com/nt/ syntax-args.html)並在那裏使用普通的'%' - 擴展;參考也[函數的概念](https://ss64.com/nt/syntax-functions.html)... – aschipfl