我在一个文件夹和一个jar文件中有10个文本文件,它们将逐个接收三个输入。
我想执行Jar文件10次(文本文件数量)。我有一个代码将执行10次并提供第一个输入"文本文件路径"
@echo off
for %%a in (*.txt) do (
echo %%a|java -jar C:\Generator.jar
)
pause
我想给剩下的两个"供应商名称和型号"作为控制台自动逐个输入。应使用下划线拆分文本文件名来填充供应商名称和模型。有没有办法实现这个目标?
答案 0 :(得分:3)
您可以使用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
。 “贝尔”会正确回应,但“豪威尔”会被解释为一个命令,几乎肯定会因错误而失败,但无论如何都不会产生预期的结果。
有关管道潜在问题的更多信息,请参阅Why does delayed expansion fail when inside a piped block of code?。
以下是我原始代码的增强功能,可以解决问题。我通过将字符串文字放在引号内来解决毒药问题,然后使用在子cmd.exe进程中执行的for
语句在ECHOing值之前安全地去除引号。
我通过使用%%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
)