您可以使用for /f 在_ 分隔符处将文件名拆分为两个标记。您不想包含 .txt 扩展名,因此您需要拆分 %%~nA 而不是 %%A。
您可以使用dir 和findstr 来验证文件名的格式是否有效,并将外部for 循环更改为for /f 以处理该结果。例如,您不想处理类似于"vendor_.txt" 的文件名。我的findstr 命令验证只有一个_,并且前后至少有一个非下划线字符。
有人会认为以下方法会起作用
@echo off
:: This does not work - each line of input to java has an unwanted trailing space
for /f "delims=" %%A in (
'dir /a-d /b *_*.txt ^| findstr /i "^[^_][^_]*_[^_][^_]*\.txt$"'
) do for /f "delims=_ tokens=1*" %%B in ("%%~nA") do (
echo %%A
echo %%B
echo %%C
) | java -jar c:\generator.jar
但是由于管道的每一端都在一个新的 cmd.exe 进程中执行,因此存在一个潜在的问题。管道的每一侧都必须被解析并打包成一个cmd /c .... 命令。左侧最终看起来像:
C:\Windows\system32\cmd.exe /S /D /C"echo fileName &echo vendor &echo model ",
每行末尾都有一个不需要的空格。添加像(echo %%A) 这样的括号没有帮助。
如果任何文件名包含像& 这样的有毒字符,则会出现另一个潜在问题。如果您的供应商名称是“Bell&Howell”,那么左侧进程将尝试执行
echo Bell&Howell。 “Bell”会正确回显,但“Howell”会被解释为命令,几乎肯定会因错误而失败,但无论如何都不会给出预期的结果。
请参阅Why does delayed expansion fail when inside a piped block of code?,了解有关管道潜在问题以及处理这些问题的策略的更多信息。
以下是对我的原始代码的增强,应该可以解决问题。我通过将字符串文字放在引号中来解决毒字符问题,然后使用在子 cmd.exe 进程中执行的 for 语句在 ECHO 值之前安全地去除引号。
我通过使用%%echoX%%“宏”延迟解析命令来解决不需要的尾随空格问题。双百分比延迟了“宏”的扩展,直到我们处于子进程之后。
@echo off
setlocal disableDelayedExpansion
:: This echoX "macro" delays parsing of the echo command to avoid the unwanted trailing space
set "echoX=(echo %%~X)"
for /f "delims=" %%A in (
'dir /a-d /b *_*.txt ^| findstr /i "^[^_][^_]*_[^_][^_]*\.txt$"'
) do for /f "delims=_" tokens=1*" %%B in ("%%~nA") do (
(for %%X in ("%%~A" "%%B" "%%C") do @%%echoX%%) | java -jar c:\generator.jar
)
另一种选择是定义一个带有嵌入换行符的多行变量,然后使用 CMD /V:ON 在子进程中启用延迟扩展。
@echo off
setlocal disableDelayedExpansion
for %%L in (^"^
%= This creates a quoted linefeed character in the FOR variable L =%
^") do for /f "delims=" %%A in (
'dir /a-d /b *_*.txt ^| findstr /i "^[^_][^_]*_[^_][^_]*\.txt$"'
) do for /f "delims=_" tokens=1*" %%B in ("%%~nA") do (
set "str=%%A%%~L%%B%%~L%%C"
cmd /v:on /c "(echo !str!)" | java -jar c:\generator.jar
)
这是一个更简单的替代方法,它使用临时文件而不是管道。它避免了管道可能出现的许多问题。
@echo off
for /f "delims=" %%A in (
'dir /a-d /b *_*.txt ^| findstr /i "^[^_][^_]*_[^_][^_]*\.txt$"'
) do for /f "delims=_" tokens=1*" %%B in ("%%~nA") do (
>temp.txt (
(echo %%~A)
(echo %%B)
(echo %%C)
)
<temp.txt java -jar c:\generator.jar
del temp.txt
)