从变量中批量提取路径和文件名

101

我怎样从一个变量中提取路径和文件名?

Setlocal EnableDelayedExpansion
set file=C:\Users\l72rugschiri\Desktop\fs.cfg

我想在不使用任何函数或任何GOTO的情况下做到这一点。这可能吗?


2
可能是批处理中如何从完整路径中拆分文件名?的重复问题。 - iTayb
5个回答

170
@ECHO OFF
SETLOCAL
set file=C:\Users\l72rugschiri\Desktop\fs.cfg
FOR %%i IN ("%file%") DO (
ECHO filedrive=%%~di
ECHO filepath=%%~pi
ECHO filename=%%~ni
ECHO fileextension=%%~xi
)

不是很确定你所说的“没有函数”是什么意思。

显然,将ECHO更改为SET以设置变量而非输出它们...

有关完整列表,请参见for 文档


ceztko的测试用例(供参考)

@ECHO OFF
SETLOCAL
set file="C:\Users\ l72rugschiri\Desktop\fs.cfg"
FOR /F "delims=" %%i IN ("%file%") DO (
ECHO filedrive=%%~di
ECHO filepath=%%~pi
ECHO filename=%%~ni
ECHO fileextension=%%~xi
)

评论:请查看评论。


1
@meir - 是的;我已经发布了一个更正。在几年的时间里,你会学到很多东西。 - Magoo
@TrivisionZero:不,引号在文件名或路径包含空格的情况下是必需的。 - Magoo
@ceztko:请详细解释一下包含“/f”的作用。 - Magoo
抱歉,我正在撤销更改,因为我注意到在路径中存在空格的情况下,使用/F选项不再起作用。尽管如此,在我的用例(shell扩展)中,您的代码仍然存在问题。我不会再进行编辑,并建议您在我的情况下进行修复,如果我能找到它的话。 - ceztko
@AlexT:嗯,它肯定不应该。没有引号,file中每个空格/逗号/制表符分隔的字符串部分都应依次应用于元变量%%i。如果file包含引号,则额外的引号是适得其反的,但正如上面的评论所解释的那样,我认为在分配给变量的值中包含引号并不是一个好主意,因为这会导致需要进行各种花式操作才能在需要时将它们删除,而添加引号则是一项简单的任务。你的情况可能有所不同。 - Magoo
显示剩余6条评论

163

你只能从以下三个位置提取路径和文件名:(1) BAT 参数本身的 %1,(2) CALL 参数的 %1 或 (3) 一个本地 FOR 变量 %%a


HELP CALLHELP FOR 中,你可以找到更详细的信息:

%~1 - 扩展 %1 并去除任何周围的引号 (")
%~f1 - 将 %1 扩展为完全限定的路径名
%~d1 - 将 %1 扩展为仅驱动器号
%~p1 - 将 %1 扩展为仅路径
%~n1 - 将 %1 扩展为仅文件名
%~x1 - 将 %1 扩展为仅文件扩展名
%~s1 - 扩展的路径仅包含短名称
%~a1 - 将 %1 扩展到文件属性
%~t1 - 将 %1 扩展到文件的日期/时间
%~z1 - 将 %1 扩展到文件大小


然后尝试以下操作:

将要解析的字符串作为参数传递给 CALL。

call :setfile ..\Desktop\fs.cfg
echo %file% = %filepath% + %filename%
goto :eof

:setfile
set file=%~f1
set filepath=%~dp1
set filename=%~nx1
goto :eof

或者等效方式,将文件名作为本地FOR变量传递

for %%a in (..\Desktop\fs.cfg) do (
    set file=%%~fa
    set filepath=%%~dpa
    set filename=%%~nxa
)    
echo %file% = %filepath% + %filename%

17

所有这些都适用于我:

@Echo Off
Echo Directory = %~dp0
Echo Object Name With Quotations=%0
Echo Object Name Without Quotes=%~0
Echo Bat File Drive = %~d0
Echo Full File Name = %~n0%~x0
Echo File Name Without Extension = %~n0
Echo File Extension = %~x0
Pause>Nul

输出:

Directory = D:\Users\Thejordster135\Desktop\Code\BAT\

Object Name With Quotations="D:\Users\Thejordster135\Desktop\Code\BAT\Path_V2.bat"

Object Name Without Quotes=D:\Users\Thejordster135\Desktop\Code\BAT\Path_V2.bat

Bat File Drive = D:

Full File Name = Path.bat

File Name Without Extension = Path

File Extension = .bat

3

如果你想获取正在运行的批处理文件的信息,可以尝试以下方法:

@echo off
set myNameFull=%0
echo myNameFull     %myNameFull%
set myNameShort=%~n0
echo myNameShort    %myNameShort%
set myNameLong=%~nx0
echo myNameLong     %myNameLong%
set myPath=%~dp0
echo myPath         %myPath%
set myLogfileWpath=%myPath%%myNameShort%.log
echo myLogfileWpath %myLogfileWpath%

需要更多示例吗? C:> HELP CALL

%0 = 参数0 = 批处理文件 %1 = 参数1 - 传递给批处理文件的第一个参数...所以您可以在第一个参数(例如“%”)和最后一个参数(例如“1”)之间尝试使用该内容(例如“〜dp”)。


1
晚了一步,我知道,但对我来说,以下脚本非常有用 - 它也回答了问题,一举两得 ;-)
下面的脚本扩展了文件资源管理器上下文菜单中的“发送到”选项:
@echo off
cls
if "%~dp1"=="" goto Install

REM change drive, then cd to path given and run shell there
%~d1
cd "%~dp1"
cmd /k
goto End

:Install
rem No arguments: Copies itself into SendTo folder
copy "%0" "%appdata%\Microsoft\Windows\SendTo\A - Open in CMD shell.cmd"

:End

如果您通过双击运行此脚本而没有任何参数,它将复制自身到SendTo文件夹并将其重命名为"A - Open in CMD shell.cmd"。然后在“SentTo”上下文菜单中可用。
然后,在Windows资源管理器中右键单击任何文件或文件夹,选择"SendTo > A - Open in CMD shell.cmd" 该脚本将更改驱动器和路径以包含您选择的文件或文件夹的路径,并打开具有该路径的命令shell - 对于Visual Studio Code非常有用,因为然后您只需键入“code .”即可在项目的上下文中运行它。
它是如何工作的? %0 - 批处理脚本的完整路径
%~d1 - 第一个参数中包含的驱动器(例如“C:”)
%~dp1 - 第一个参数中包含的路径
cmd /k - 打开保持打开的命令shell

这里未使用,但%~n1是第一个参数的文件名。
我希望这对某人有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接