如何从cmd批处理文件中的变量获取目录路径

3

在我的批处理文件中,我有一个包含文件路径的变量:

SET VAR1=C:\Folder1\Folder2\File.txt

我希望能够提取目录结构并检索以下内容:
C:\Folder1\Folder2\

我读过像这样的帖子,需要使用%~dp0,其中0我相信是作为参数传递的。我尝试了%~dpVAR1,但那不起作用。如何使用包含文件路径的变量来获得所需的输出结果?
另外,为了让事情变得更加困难,我必须在一个IF条件中执行所有操作,这意味着一旦变量被声明,我将需要使用!而不是%来引用它(我在脚本开头声明了setlocal enableextensions enabledelayedexpansion以允许这样做)。
非常感谢您的帮助!
谢谢!
安德鲁
4个回答

8
您正在尝试在环境变量上使用参数扩展语法 - 这是无法实现的。但是,实现您想要的内容相对容易。
使用CALL(速度相对较慢):
(...
  call :getPath "!var!" var
  ...
)
exit /b

:getPath
set "%2=%~dp1"
exit /b

使用FOR循环,假设变量不包含任何通配符(快速)。
(...
  for %%F in ("!var!") do set "var=%%~dpF"
 ...
)

使用FOR命令时,如果变量包含通配符(也很快)
(...
  for /f "delims=" %%F in ("!var!") do set "var=%%~dpF"
 ...
)

注意1:如果变量不包含完整路径,则所有解决方案都会尝试将名称解析为绝对路径,并返回完整的绝对路径。例如,如果var包含foobar\test.txt,则即使找不到文件,解决方案也将包括当前目录的完整路径。类似于c:\pathToCurrentDirectory\foobar\
注意2:上述所有解决方案都将从路径中删除所有引号。
注意3:路径可能包含!字符,这会在扩展%~dp1%%~dpF时导致问题,因为启用了延迟扩展。如果值包含!,延迟扩展将破坏^!。有一种解决方案涉及保护!^。以下是应用于上面最后一个解决方案的演示。该保护需要正常扩展,并且由于您在代码块内部,因此至少需要一个CALL。它可以在没有子例程的情况下完成,但使用子例程更容易。子例程假定变量名为var
(...
  call :getPath
 ...
)
exit /b

:getPath
set "var=!var:"=!"
set "var=!var:^=^^^^!"
set "var=%var:!=^^^!%" !
for /f "delims=" %%F in ("!var!") do set "var=%%~dpF" !
exit /b

你有什么想法,为什么在去掉引号和感叹号后,第二个示例才能正常工作? - fordareh
@fordareh - 问题明确地尝试从变量的内容中提取路径信息。如果没有感叹号,它是无法工作的。你必须做一些与问题直接无关的事情。 - dbenham

1

我相信(再一次)许多问题都涉及相同的主题(字符串约束或拆分字符串)。

不是把整个代码给你,而是给你一个模板,并解释为什么 %~dpVAR! 不起作用。

首先,为什么 %~dpVAR! 不起作用。

在讨论修改器之前,让我们先讨论参数。你可能知道批处理文件可以相互解析参数。这些参数可以通过在数字0-9前面使用单个百分号(%)来调用。据我所知(有人可能已经找到了一种解析更多参数的方法),只能解析9个参数。你可能认为这是错误的(有10个参数对吧?)。参数1-9被解析到批处理文件(或其中一个函数),%0是批处理文件的文件路径(或函数名称)。如果你看一下,%~dp0 与 %0 有一些相似之处(不是真的)。下面将讨论这一点。

其次,术语%~dp0中包含修饰符。修饰符是修改变量的东西(仅适用于参数和在for循环中声明的那些变量,你知道那些带有双百分号的变量,如%%i),以及参数。修饰符d将参数扩展为驱动器号,而p仅将参数扩展为路径。您可能认为这些会相互矛盾,但可以组合参数以创建极其奇怪的格式。
因此,您尝试将0替换为您的变量名称失败,因为它未针对此类事物指定。
现在,进入模板。
您可以像这样限制变量(并将它们放入其他变量):set variable=!variable:~offset,amount! 如果这看起来令人困惑,请不要担心,我即将解释其中的组件。
首先,请注意没有/a开关。这是因为这不是数学函数(不太清楚为什么我添加了这个)。因此,在我解释之前,这里是一个示例,说明它将对变量名为numbers且值为0123456789的变量执行的操作。
set numbers=!numbers:~5,1!

通过使用这行代码,numbers现在将等于5。这是因为它正在重新创建一个变量,使用原始值的较小版本(这很难解释)。正如您在上面的模板中看到的,offset的位置有一个5。这是因为它跳过了前5个字符,并将变量设置为下一个amount,即1个字符(我真的希望你能理解这个)。
所以基本上,它将一个变量设置为另一个(或相同)变量的较短值,由偏移量和要包含其中的字符数确定。
我真的希望这可以帮助您,因为我可能不会理解这些话。
有人能把这个可怜的家伙重定向到一个更好的解释链接吗?(我试过了,好吧!)

2
你对于为什么OP的代码无法工作的解释很好,尽管有点啰嗦。剩下的关于子字符串操作的部分与手头的问题无关。 - dbenham

0

从变量中提取路径的完整示例:

@echo off
set /p Fullpath="Specify full path: "
call :getPath %Fullpath% filename folder
echo %filename%
echo %folder%
pause
exit /b

:getPath
set "%2=%~nx1"
set "%3=%~dp1"
exit /b

-2
这个可以吗:
SET VAR1=C:\Folder1\Folder2\File.txt
echo %var1%

Echo 是你的可执行文件的名称。

%CD% 也可能有效:Echo %CD%


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