1

我正在创建一个批处理文件以在 Windows XP 机器上静默安装 nodejs。

我正在尝试自动安装节点模块依赖项(npm install)。

我通常会从目标安装目录中的 cmd 提示符发出 npm install 。

我正在努力自动化与批处理文件中的命令提示符的交互。

我的批处理脚本中的以下行似乎使我可以将命令的文本文件通过管道传输到 cmd:

for /F "usebackq delims=," %%i in ("c:\foo\source\npm_install.txt") do echo %%i | "c:\windows\system32\cmd.exe"

批处理文件位于 c:\foo\source 中。我需要从 c:\foo\bin 发出“npm install”。

如果我的 npm_install.txt 文件是这样的:

  cd /d c:\foo\bin,     
  npm install

cmd 提示符将执行第一个命令,将目录从 c:\ 更改为 c:\foo\bin。

然后它将执行第二个命令,但再次从 c:\ 开始。先前更改目录的命令不会持续存在。似乎文本文件中的每个命令都将从 c:\ 发出。

接下来我尝试从一个组合语句中发出这两个命令:

  cd /d c:\foo\bin && npm install

似乎这种方法可以让我克服之前的路径问题,但是我遇到了 npm 和 install 之间的空间问题。

cmd 提示符执行 c:\foo\bin>npm 并导致 npm 在空间上跳闸。

我试过封闭命令但没有成功:'npm install',“npm install”,(npm install)。

谁能告诉我我做错了什么?

谢谢。

4

3 回答 3

2

问题是您的批处理脚本正在创建一个新的子shell 来处理安装文件中的每一行。因此,您的cd命令在子shell 中执行,更改其工作目录,但随后子shell 退出,您又回到父shell 的工作目录。

您的主脚本可以只是call您的安装脚本(其扩展名必须更改为“.bat”)吗?call允许您在同一个 shell 中运行另一个批处理文件,然后继续运行您的原始脚本。

于 2012-09-08T14:56:59.943 回答
1

你不需要这个: do echo %%i | "c:\windows\system32\cmd.exe". 只需将您的命令放在一个块中。

do (
  command
  command
  ...
)

使用您之前的语句,您启动新的 cmd 解释器,要求它为您执行命令并退出 - 这就是您失去cd.

如果您没有在 for 循环中指定标记,则仅读取第一个。另外,所有标记必须在同一行(我不确定您显示的内容是否不是格式化的副产品)"delims="用于阅读整行。

如果不需要,请勿将命令与参数混合:仅将目录放入文件中:

c:\foo\bin
c:\bar\bin

所以最后它变成了(我用 pushd/popd 替换了 cd 所以你最终会在你开始的同一个目录中):

for /F "usebackq delims=" %%i in ("c:\foo\source\npm_install.txt") do (
      pushd %%i 
      npm install
      popd 
    )

编辑:如果npm install是批处理本身,您将需要使用调用,如ebohlman所述

于 2012-09-08T15:00:36.960 回答
0

注意:这三个示例不需要您将CALL任何批处理文件放在前面,每个批处理文件都内置了该功能。

最小和最简单的,它只是执行带有参数的命令:

@echo off
for /f "tokens=*" %%x in (c:\foo\source\npm_install.txt) do (
  call %%x
)

要模仿一个人在键盘上键入命令:

@echo off
for /f "tokens=*" %%x in (c:\foo\source\npm_install.txt) do (
  setlocal enabledelayedexpansion
    :: Mimic commandline
    call set "cmd=%%cd%%"
    echo !cmd!^>%%x
  endlocal
  :: Preform command
  call %%x
  echo.
)

无论脚本在哪里结束,都要在您开始时所在的同一目录中结束:

@echo off
setlocal enabledelayedexpansion
for /f "tokens=*" %%x in (c:\foo\source\npm_install.txt) do (
    :: Mimic commandline
    call set "cmd=%%cd%%"
    echo !cmd!^>%%x
  :: Preform command
  call %%x
  echo.
)
endlocal
于 2012-09-08T22:12:20.200 回答