【问题标题】:Multistep console inputs for a command in Batch File批处理文件中命令的多步控制台输入
【发布时间】:2017-07-05 05:41:09
【问题描述】:

我在一个文件夹中有 10 个文本文件和一个 jar 文件,它会一一接受三个输入。

  1. 文本文件路径
  2. 供应商名称
  3. 型号

我想执行 10 次 Jar 文件(文本文件的数量)。我有一个将执行 10 次并提供第一个输入“文本文件路径”的代码

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

我想自动将剩余的两个“供应商名称和型号”作为控制台输入。供应商名称和型号应通过使用下划线拆分文本文件名来填充。有没有办法做到这一点?

【问题讨论】:

  • for %%a in ("*.txt") do for /F "usebackq tokens=1-3 delims=_ eol=_" %%b in ("%%~a") do ((echo/%%b&echo/%%c&echo/%%d) | java -jar C:\Generator.jar)
  • @aschipfl - 您使用usebackq 需要in ('%%~a')。此外,第一个输入是整个文件名,而不是从名称解析的值。但最糟糕的是,java 的每一行输入都会有一个不需要的尾随空格。见my answer
  • @dbenham,我误解了这个问题,并认为供应商名称和型号是文本文件的内容,而不是它们的名称;这就是我使用usebackq 的原因。你对尾随空格是对的,我的评论只是一个快速的镜头,我并没有真正考虑过它们。顺便说一句,答案很好!

标签: batch-file command


【解决方案1】:

您可以使用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。 “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
)

【讨论】:

  • 这个答案应该被标记为最喜欢的,只要它可能+1。
猜你喜欢
  • 1970-01-01
  • 2011-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多