【问题标题】:Last index of a character in an input string in a batch file批处理文件中输入字符串中字符的最后索引
【发布时间】:2016-09-17 05:39:17
【问题描述】:

我有一个在 Windows 中运行的批处理脚本。每次调用批处理脚本时,都会提供一个输入路径作为参数。我需要从路径中提取文件夹名称。为此,我需要从路径中获取“/”的最后一个索引,然后从该路径中获取一个子字符串,直到字符串结尾。

假设我有一个字符串 /home/home1/home2/home3

我需要的输出是 home3。有什么方法可以提取相同的。

【问题讨论】:

  • 在 Windows 中,您应该使用反斜杠作为路径分隔符,否则某些命令可能会出现问题...
  • 您想要路径中“/”的最后一个索引还是路径中的最后一个文件夹名称?问题标题表示重要数据是一个字符的索引,但是最后一个文件夹可以提取而不使用索引!我建议您将问题集中在真正的问题(如“文件夹名称”)上,不要插入不相关的数据(如“字符索引”)。

标签: batch-file


【解决方案1】:

对于普通的 DOS/Windows 批处理文件,这应该可以工作:

set FILE="c:\foo\bar.txt"
for /F %%i in ("%FILE%") do @echo %%~ni

来自DOS BAT file equivalent to Unix basename command?

Windows PowerShell 和 Unix shell 提供了其他选择。

【讨论】:

  • 谢谢托德! :)
  • 不仅 /F 不是必需的,如果路径中有空格也会导致问题,除非 DELIMS 设置为空。此外,它应该是%%~nxi,因为文件夹名称可以包含点。
  • 如果原始路径有一个尾部反斜杠,这将失败。还有其他深奥的边缘情况。见my answer
【解决方案2】:

所以你有一个代表文件夹路径的字符串,并且你想要路径中最右边的文件夹的名称。 CMD.EXE 提供了方便的工具来处理文件/文件夹路径,因此无需搜索最后的\

您没有说明字符串所在的位置。很可能是 1) 在从 CALL 到批处理脚本或 :function 的批处理参数中,或 2) 在环境变量中。我将假设一个参数,并展示一系列解决方案,每个解决方案都比前一个更好(更稳健)。最后,我将稍微调整一下以适应使用环境变量。

所以如果参数%1 包含/home/home1/home2/home3,那么你只需要%~n1

但文件夹名称可以包含点,最后一个点之后的文本被认为是扩展名。因此,您还需要 x 修饰符来包含扩展名。例如,如果%1 包含/home.1/home.2/home.3,那么%~nx 将产生home.3。如果没有扩展,它也可以工作。

但文件夹名称可能包含像& 这样的毒字符,因此您应该将字符串括在引号中:"%~nx1"。如果要将结果分配给变量,则应将整个分配用引号括起来:set "folder=%~nx1"。该值不会包含引号,因此扩展变量时请务必添加引号:"%folder%",否则使用延迟扩展!folder!

但有时人们在传递文件夹路径时会包含尾部反斜杠,例如\home1\home2\home3\。尾部的反斜杠肯定表示该路径是一个文件夹,但%~nx1 不会产生任何结果。有一个使用 FOR 循环和附加点的简单技巧来解决这个问题。

for %%F in (%1.) do set "folder=%%~nxF"

请注意,FOR 变量使用与参数完全相同的修饰符。附加的点以一种巧妙的方式优雅地解决了这个问题。如果尾部有反斜杠,则该点表示该位置的“当前”目录。扩展修饰符自动将结果规范化为规范形式,从而产生正确的答案。但如果没有尾随反斜杠,它也可以工作。文件和文件夹名称不允许以点或空格结尾,扩展规范化会去除尾随点。

还有一些其他涉及 UNC 路径和长路径的深奥案例可以通过添加 ~f 修饰符将 %1 转换为完整的规范路径来解决。

这是应该“始终”使用批处理参数%1 的最终解决方案。

for %%F in ("%~f1.") do set "folder=%%~nxF"

我将“始终”一词放在引号中,因为代码可能会失败,但这需要最终用户做一些愚蠢的事情,比如传递"c:\This"^&"that\"。在这种情况下,正确的做法是简单地传递"c:\This&that\"

请注意,传递的路径可能是卷的根目录,例如“c:\”。在这种情况下,结果是一个空字符串,这是正确的 - 没有文件夹名称。

如何改为使用环境变量

假设您有包含路径字符串的变量folderPath。如果您知道该值不包含任何引号,并且它不是 UNC 或长路径,那么您可以简单地使用:

for %%F in ("%folderPath%.") do set "folder=%%~nxF"

但如果值已经包含引号,或者它是 UNC 或长路径,则可能会以多种方式失败。解决方案是添加一个额外的 FOR /F 循环以及延迟扩展,以安全地将值传输到 FOR 变量中。然后~f 修饰符可以像以前一样使用。但是路径可以包含! 字符,如果启用延迟扩展,FOR 变量扩展将删除任何!。所以延迟扩展必须有策略地打开和关闭。

这是使用变量的终极解决方案

我假设延迟扩展目前已关闭。

setlocal enableDelayedExpansion
for /f "eol=: delims=" %%A in ("!folderPath!") do (
  endlocal
  for %%F in ("%%~fA.") do set "folder=%%~nxF"
)

我不知道最后一个代码可能会失败的任何情况。

【讨论】:

    猜你喜欢
    • 2013-01-11
    • 1970-01-01
    • 2014-03-13
    • 2013-02-03
    • 2011-02-15
    • 1970-01-01
    • 2014-05-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多