批处理文件中命令的多步控制台输入

时间:2017-07-05 05:41:10

标签: batch-file command

我在一个文件夹和一个jar文件中有10个文本文件,它们将逐个接收三个输入。

  1. 文本文件路径
  2. 供应商名称
  3. 模型
  4. 我想执行Jar文件10次(文本文件数量)。我有一个代码将执行10次并提供第一个输入"文本文件路径"

    @echo off
    for %%a in (*.txt) do (
        echo %%a|java -jar C:\Generator.jar
    )
    pause
    

    我想给剩下的两个"供应商名称和型号"作为控制台自动逐个输入。应使用下划线拆分文本文件名来填充供应商名称和模型。有没有办法实现这个目标?

1 个答案:

答案 0 :(得分:3)

您可以使用for /f将文件名拆分为_分隔符中的两个令牌。您不希望包含.txt扩展名,因此您需要拆分%%~nA而不是%%A

您可以dirfindstr一起使用来验证文件名是否具有有效格式,并将外部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
)