拆分路径并在批处理脚本中取最后一个文件夹名称
Posted
技术标签:
【中文标题】拆分路径并在批处理脚本中取最后一个文件夹名称【英文标题】:split path and take last folder name in batch script 【发布时间】:2013-06-21 04:11:29 【问题描述】:我想用\
分割字符串(有路径)并在变量中取最后一个文件夹名称。请帮忙。
例如 mypath=D:\FOLDER1\FOLDER2\FOLDER3\
我想要一个变量中的 FOLDER3。
如果最后一个字符不是\
,我尝试使用以下命令:
for %f in (C:\FOLDER1\FOLDER2\FOLDER3) do set myfolder=%~nxf
如果最后一个字符是\
则不起作用
如果使用以下变量,它也不起作用: 对于 (%mypath%) 中的 %f,请设置 myfolder=%~nxf
【问题讨论】:
【参考方案1】:@echo off
set MYDIR=C:\FOLDER1\FOLDER2\FOLDER3\
set MYDIR1=%MYDIR:~0,-1%
for %%f in (%MYDIR1%) do set myfolder=%%~nxf
echo %myfolder%
输出
FOLDER3
【讨论】:
%MYDIR:~0,-1%
似乎是某种子字符串方法,但有人能解释一下 for 循环中发生了什么吗?
我的文件夹中缺少最后一个字符!所以它实际上不起作用。输入文件夹:..\blalalalal\Control-Freak 返回:Control-Frea
看起来是因为你最后没有斜杠。如果您附加一个,则上述方法将起作用。
或者你可以去掉set MYDIR1=%MYDIR1:~0,-1%
这行实际上删除了最后一个字符。为了安全起见,您可以检查是否有斜杠,如果有,则删除最后一个字符,如果没有,则保留字符串原样:)
当路径中有空格时,上述方法不起作用。例如,如果路径设置为 MYDIR=C:\FOLDER1\FOLDER2\FOLDER 3\ 它将返回 3 而不是 FOLDER 3【参考方案2】:
尝试:
for %f in (C:\FOLDER1\FOLDER2\FOLDER3\.) do set myfolder=%~nxf
也可以:
for %f in (C:\FOLDER1\FOLDER2\FOLDER3.) do set myfolder=%~nxf
【讨论】:
【参考方案3】:当您当前的文件夹包含空格时,请尝试以下操作:
@echo off
for %%f in ("%CD%") do set LastPartOfFolder=%%~nxf
echo %LastPartOfFolder%
【讨论】:
【参考方案4】:把它放在一个可以正确处理空格的简单子程序中:
@Echo Off
Rem Get name of folder containing this script.
Call :ParentFolderNamGet "%~dp0"
Rem Debug the variable.
Echo ParFldNam is [%ParFldNam%]
Pause
Rem Done with this script.
GoTo :EOF
Rem Argument to this subroutine must be a validly-formatted path (ends with a trailing backslash).
:ParentFolderNamGet
Rem Drop any enclosing double-quotes from caller's path, ensuring the last character is the path's trailing backslash.
Set Prm=%~1
Rem Drop trailing backslash; this converts the string from %~dp1 to %~dpn1 (the last folder name becomes a file name).
Set Prm=%Prm:~0,-1%
Rem Get only the 'filename' portion from the validly-formatted pathname.
For %%A In ("%Prm%") Do Set ParFldNam=%%~nxA
Rem Result is in %ParFldNam%
GoTo :EOF
【讨论】:
【参考方案5】:下面的脚本包含一个子例程,它将处理带有和不带有斜杠的路径,以及相同的示例测试。
@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
我知道它看起来很长,但这只是由于测试用例和大量 cmets;主子程序代码大约有 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/ (自从我上次查看以来,此页面上的 CSS 变得很乱,但您可以将文本复制到文件中并没问题。)
【讨论】:
【参考方案6】:这对我有用,不管路径是否有空格、特殊字符(& 或类似字符)或末尾的 \(或没有)。
setlocal ENABLEDELAYEDEXPANSION
set "par=%~1"
:loop
for /f "delims=\ tokens=1,*" %%A in ("%par%") do (
set "_last=%%A"
set "par=%%B"
)
if NOT "%par%"=="" goto loop
echo Folder last name is :!_last!:
【讨论】:
【参考方案7】:写得很棒的家伙。不过我喜欢简单...
rem set with or without spaces or trailing slash, but quotes are important...
set "_foldername=..."
rem cd command doesn't care if there's a trailing slash or not, and don't forget quotes...
cd "%_foldername%" rem or pushd/popd if desired
rem as per @Dirk, use the %cd% system variable instead of the manually set variable,
rem this will return the current directory, always w/o a trailing slash.
rem again, as per @Dirk, quotes cause it to do spaces correctly.
for %%f in ("%cd%") do set _lastfolder=%%~nf
rem popd here, if used.
echo %_lastfolder%
简单吧?
那么...为什么每个人都使用%nxf%
(文件名)而不是%nf%
(文件夹)?
【讨论】:
你甚至不需要~n
,因为~f
包含~dpnx
。但是您的灵魂仅适用于现有路径。如果您有稍后要创建的路径或只想检查,它会失败
why is everyone using %nxf% (filename) instead of %nf% (folder)?
- 因为文件夹名称可能包含一个点。 (顺便说一句:%~nf
不是folder
,而是file (or folder) name without extension
)以上是关于拆分路径并在批处理脚本中取最后一个文件夹名称的主要内容,如果未能解决你的问题,请参考以下文章
Windows批处理脚本:查找目录中最后一个文件夹的名称[关闭]
在批处理文件中拆分以逗号分隔的字符串并在循环中调用 sqlplus 函数
批处理脚本 - dir /b 在输出文件中包含目录名称和空行