下面的脚本包含一个子例程,它将处理带有和不带有斜杠的路径,以及相同的示例测试。
@echo off
::-----------------------------------------------------------------------------
:: Main script - testing the :get_last_folder subroutine.
::-----------------------------------------------------------------------------
setlocal enableExtensions
:: no trailing slash
call :get_last_folder C:\path\to\folder_0 _result
echo result: %_result%
:: one trailing slash
call :get_last_folder C:\path\to\folder_1\ _result
echo result: %_result%
:: extra slashes -- Windows doesn't care.
call :get_last_folder C:\path\to\folder_2\\ _you_can_use_any_variable_name
echo result: %_you_can_use_any_variable_name%
:: spaces in path
call :get_last_folder "C:\path\to\folder with spaces" _result
echo result: %_result%
:: no return variable -- Subroutine will ECHO the value.
call :get_last_folder C:\path\to\folder_to_echo
:: path of current directory
call :get_last_folder "%cd%" _result
echo result: %_result%
:: path of current directory after changing it
pushd "%userprofile%"
call :get_last_folder "%cd%" _result
echo result: %_result%
:: location of this file, independent of current directory
call :get_last_folder "%~dp0" _result
echo result: %_result%
:: restore previous current directory, cuz I'm not rude.
popd
exit /b
::-----------------------------------------------------------------------------
:: Subroutine
::-----------------------------------------------------------------------------
:get_last_folder <path> [return]
:: Extracts the last folder in a file system directory path.
:: Path may include zero, one, or more trailing slashes, but not a file name.
REM Use SETLOCAL to keep our subroutine variables from affecting the parent.
REM It also allows us to limit delayed variable expansion to where it's needed.
setlocal enableDelayedExpansion
REM Add a trailing slash to ensure the last element is seen as a folder.
REM If it already had a trailing slash, that's okay: extras are ignored.
set "_full_path=%~1\"
REM The caller can provide a variable name that we'll set to the return value.
REM If no return variable is given, we'll just ECHO the value before exiting.
set "_return=%~2"
for /f "delims=" %%F in ("%_full_path%") do (
REM Treat the path as a string to avoid "file not found" error.
REM Use loop variable expansion to get the "path" part of the path.
REM The resulting string will always have exactly one trailing slash.
set "_path=%%~pF"
REM Use substring substitution to remove the trailing slash.
REM Delayed expansion lets us access the new value while inside the loop.
set "_path=!_path:~0,-1!"
REM Without a trailing slash, the last element is now seen as a file.
REM Use the "name" substring to get the value we came for.
for /f "delims=" %%D in ("!_path!") do (
set "_name=%%~nD"
)
)
REM
if defined _return (
set "_command=set %_return%=%_name%"
) else (
set "_command=echo\%_name%"
)
REM The "ENDLOCAL &" trick allows setting variables in the parent environment.
REM See https://ss64.com/nt/syntax-functions.html for more details.
endlocal & %_command%
goto :eof
我知道它看起来很长,但这只是由于测试用例和大量评论;主子程序代码大约有 10 行,如果你把它放在它自己的文件中,其中一些可能会消失。
批处理脚本子例程在由解释器或编译器评估然后返回适当的值的意义上不是真正的函数。相反,它们是一种经过修改的、花哨的 GOTO 形式,支持局部变量。尽管如此,它们对于将代码分解为可重用的部分和传递值仍然很有用。虽然“伪函数”可能是一个更好的术语,但人们通常只是说“函数”,因此搜索“批处理脚本函数”将为您提供有用的结果。
这是批处理“函数”如何工作的最古老和最好的文章之一:
https ://www.dostips.com/DtTutoFunctions.php
这是对函数的更简单、更简短的解释,并在脚本中引用:https ://ss64.com/nt/syntax-functions.html
有关 CMD 中 FOR 循环内部到底发生了什么的解释,请参阅优秀的 Rob van der Woude 的这篇文章:https ://www.robvanderwoude.com/for.php
有时阅读是不够的。这是一组很棒的练习,可以真正掌握事物:https :
//resources.infosecinstitute.com/cmd-exe-loops-part-iii/它,但您可以将文本复制到文件中并没问题。)