在批处理文件中创建子字符串的最佳方法是什么?


192

我想获取当前正在运行的批处理文件的名称,而没有文件扩展名。

多亏了此链接,我的文件名带有扩展名...但是在批处理文件中创建子字符串的最佳方法是什么?

还是有另一种方法来获取不带扩展名的文件名?

在这种情况下,可以假设3个字母扩展名是安全的。

Answers:


395

好吧,仅获取批处理的文件名,最简单的方法就是使用%~n0

@echo %~n0

将输出当前正在运行的批处理文件的名称(不带扩展名)(除非在由调用的子例程中执行call)。help for在帮助的最后,可以使用找到此类“特殊”替代路径名的完整列表:

此外,FOR变量引用的替换已得到增强。现在,您可以使用以下可选语法:

%~I         - expands %I removing any surrounding quotes (")
%~fI        - expands %I to a fully qualified path name
%~dI        - expands %I to a drive letter only
%~pI        - expands %I to a path only
%~nI        - expands %I to a file name only
%~xI        - expands %I to a file extension only
%~sI        - expanded path contains short names only
%~aI        - expands %I to file attributes of file
%~tI        - expands %I to date/time of file
%~zI        - expands %I to size of file
%~$PATH:I   - searches the directories listed in the PATH
               environment variable and expands %I to the
               fully qualified name of the first one found.
               If the environment variable name is not
               defined or the file is not found by the
               search, then this modifier expands to the
               empty string

可以组合使用修饰符以获得复合结果:

%~dpI       - expands %I to a drive letter and path only
%~nxI       - expands %I to a file name and extension only
%~fsI       - expands %I to a full path name with short names only

为了精确回答您的问题,但是:子字符串使用:~start,length表示法完成:

%var:~10,5%

将从环境变量中位置10提取5个字符%var%

注意:字符串的索引是从零开始的,因此第一个字符在位置0,第二个字符在位置1,依此类推。

为了得到参数变量如子%0%1等你给他们分配使用正常的环境变量set第一:

:: Does not work:
@echo %1:~10,5

:: Assign argument to local variable first:
set var=%1
@echo %var:~10,5%

语法更加强大:

  • %var:~-7% 从中提取最后7个字符 %var%
  • %var:~0,-4%将提取除最后四个字符以外的所有字符,这也将使您摆脱文件扩展名(假设句点[ .] 之后为三个字符)。

有关help set该语法的详细信息,请参见。


31
子字符串提取也不适用于FOR循环变量,因此您必须执行以下操作(代码中的\ r \ n表示换行,因为SO似乎不允许注释中的换行):setlocal ENABLEDELAYEDEXPANSION \r\n for /f %%s in ('set') do ( \r\n set tmp=%%s \r\n echo !tmp:~-3! \r\n )
Fr0sT 2014年

@ Fr0sT为什么要对FOR循环执行此操作?
鲍勃(Bob)

4
@Adrian为什么不呢?FOR是批处理文件中执行大量不同任务的基石。顺便说一句,还有另一种方法可以通过使用子例程来完成任务,即for /f %%s in ('set') do call :DoSmth "%%s" \r\n ... \r\n :DoSmth \r\n set var=%1 \r\n echo %var:~1,3%
Fr0sT

1
使用Windows Server 12 R2,%date%看起来像18/05/21(IT文化);正确的字符串是: %date:~0,2%%date:~3,2%%date:~6,4%%time:~0,2%%time:~3,2%%time:~6,2%
Phate01 '18

@ Phate01,请勿用于%date%以某种格式构造日期。该格式特定于用户的文化,并且可能会更改。改用WMI以不依赖于用户设置的有用格式获取日期和时间。我也不确定此评论在这里做什么,因为这个问题与日期或时间无关。
乔伊

38

上面很好地解释了!

对于像我这样可能会在本地化Windows中工作的所有用户(我的斯洛伐克语是XP),您可以尝试将其替换%!

所以:

SET TEXT=Hello World
SET SUBSTRING=!TEXT:~3,5!
ECHO !SUBSTRING!

27
请注意,这仅在setlocal ENABLEDELAYEDEXPANSION命令之后有效
Fr0sT 2014年

13

作为Joey答案的附加信息,set /?nor 的帮助中没有描述for /?

%~0扩展为自己键入的批次的名称。
因此,如果您开始批量生产,它将扩展为

%~0   - mYbAtCh
%~n0  - mybatch
%~nx0 - mybatch.bat

但是有一个例外,在子例程中扩展可能会失败

echo main- %~0
call :myFunction
exit /b

:myFunction
echo func - %~0
echo func - %~n0
exit /b

这导致

main - myBatch
Func - :myFunction
func - mybatch

在函数中,%~0始终将其扩展为函数的名称,而不是批处理文件的名称。
但是,如果使用至少一个修饰符,它将再次显示文件名!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.