I am creating a batch file to siliently install nodejs on a Windows XP machine.
I am trying to automate the installation of node module dependencies (npm install).
I would normally issue npm install from the cmd prompt in the target installation directory.
I am struggling to automate the interaction with the command prompt from a batch file.
The following line in my batch script seems to make it possible for me to pipe a text file of commands to cmd:
for /F "usebackq delims=," %%i in ("c:\foo\source\npm_install.txt") do echo %%i | "c:\windows\system32\cmd.exe"
The batch file is located in c:\foo\source. I need to issue 'npm install' from c:\foo\bin.
If my npm_install.txt file is such:
cd /d c:\foo\bin,
npm install
The cmd prompt will perform the first command changing the directory from c:\ to c:\foo\bin.
It will then perform the second command but starting from c:\ again. The previous command to change directories doesn't persist. It seems every command in the text file will be issued from c:\ .
I next tried to issue both commands from a combined statment:
cd /d c:\foo\bin && npm install
It seems this approach will allow me to overcome the prior path problem but I then have an issue with the space between npm and install.
The cmd prompt performs c:\foo\bin>npm and causes npm to trip on the space.
I have tried enclosing the command without success: 'npm install', "npm install", (npm install).
Can anyone tell me what I am doing wrong?
Thanks.
The problem is that your batch-processing script is creating a new subshell to handle each line in your install file. Thus your cd command is executed in a subshell, changing its working directory, but then the subshell exits and you're back in the parent shell's working directory.
Can your main script simply call your install script (whose extension would have to be changed to ".bat")? call lets you run another batch file in the same shell and then continue running your original script.
You do not need this:
do echo %%i | "c:\windows\system32\cmd.exe". Simply put your commands in a block.
do (
command
command
...
)
With your previous statement, you start new cmd interpreter, ask it to execute a command for you and exit - that's why you loose effect of that cd.
If you do not specify tokens in for loop, only 1st is read. Plus, all tokens must be on same line (I'm not sure if what you show is not a byproduct of formatting)
Use "delims=" to read full line.
Do not mix commands with arguments if you do not have to: put only directories in your file:
c:\foo\bin
c:\bar\bin
so finally it becomes (I replaced cd with pushd/popd so you'll end up in the same dir you started from):
for /F "usebackq delims=" %%i in ("c:\foo\source\npm_install.txt") do (
pushd %%i
npm install
popd
)
Edit: if npm install is batch itself, you will need to use call, as ebohlman noted
NOTE: These three examples do not require you to put CALL in front of any batch files, that functionality is built-into each.
The smallest and simplest, it just executes the commands with their arguments:
#echo off
for /f "tokens=*" %%x in (c:\foo\source\npm_install.txt) do (
call %%x
)
To mimic a person typing the commands at the keyboard:
#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.
)
To end up in the same directory you started in, no matter where the script ends:
#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
Related
I am not sure if this is possible, but would be very useful to me if it is.
I am using a .bat file which calls a js file with some node.js code in it.
e.g.
call node prepare.js
In the js file I want to do some work and the output of this I would like to return to the cmd line or have a variable set on the cmd line for use later in the bat file.
Anyone done such a thing?
May be you need the for command?
for /f "tokens=* delims=" %%a in ('node prepare.js') do (
set "output=%%a"
)
echo %output%
This node app for work starts up with a starter script in batch. The cmd window stays there after launch and it opens up the correct port, but it always launched the browser too fast so it showed a 404. After npm launched you could refresh the page and it launches fine.
#echo off
#setlocal
set NODE_HOME=%~dp0/nodejs
set PATH=%NODE_HOME%;%PATH%
call npm install
start http://localhost:8090/
call npm start
I wanted to tweak this a bit to have it wait a few seconds before launching the browser. So I figured I just need to open localhost after npm start is outputting "ready for work" to the CLI. But that command actually never 'finishes' so open localhost is never executed. I tried to resolve it like this:
#echo off
#setlocal
SET NODE_HOME=%~dp0/nodejs
SET PATH=%NODE_HOME%;%PATH%
CALL npm install
START /B CMD /C CALL openlocalhost8090.cmd
CALL npm start
And this is what openlocalhost.cmd looks like:
#echo off
TIMEOUT /T 5 /NOBREAK >NUL
START http://localhost:8090/
It actually launches fine and it waits in the background at the same time as npm start is executed so the browser launches without 404 and the app runs fine! But now that I'm testing it again the cmd window disappears after launching the browser. This is quite inconvenient because I'd still like to see log output and be able to stop the server by closing the cmd window. That's how it was with the original script. I need to go into task management to find the process to stop it now.
How can I fix this to make the cmd window stay alive?
Also, is there a better way to handle this 404 "bug"? (I love bash, I could just use open localhost:8090 & npm start and be done!)
Edit: After suggestions by #Mofi this is what I came up with:
#echo off
#setlocal
SET NODE_HOME=%~dp0nodejs
SET PATH=%NODE_HOME%;%PATH%
CALL "%NODE_HOME%\npm.cmd" install
START /B CMD /K CALL openlocalhost8090.cmd
CALL "%NODE_HOME%\npm.cmd" start
I still do the subscript with openlocalhost8090.cmd because contrary to what #Mofi claims that just putting open localhost and call npm start under each other will solve my issue, it doesn't. Putting everything directly under each other is what was wrong with the first script and what I wanted to solve. The browser is started too fast so it 404's before npm can start. If this is not what you meant #Mofi, then I'm sorry but I didn't find your answer very clearly written.
The /K flag after CMD however prevents the cmd window from closing and solves that issue, so thank you for that!
1. Complete definition of execution environment for batch file
The usage of just #setlocal results in creating a copy of existing list of environment variables, pushing current directory path on stack as well as the states of command extensions and delayed expansion without changing the state for command extensions and of delayed environment variable expansion. So the command is incomplete to define completely the execution environment for the batch file. The execution environment still depends on what is defined for command extensions and delayed expansion outside the batch file which is in general not good for any batch file.
The perfect command line to define execution environment is for this batch file:
setlocal EnableExtensions DisableDelayedExpansion
2. Correct variable definition using batch file path
The command line set NODE_HOME=%~dp0/nodejs is not good because of
\ is the directory separator on Windows and not / as on Linux/Mac as it can be read in Microsoft documentation about Naming Files, Paths, and Namespaces and
%~dp0 expands to a path always ending already with a backslash and for that reason no additional backslash should be added on concatenating the full batch file path with a file/folder name or a wildcard pattern which Windows has to remove later on every usage of the path containing now inside \\ and
the entire argument string of command SET is not enclosed in double quotes which results in this command line does more than just assigning a folder path to environment variable NODE_HOME on full path of batch file contains by chance one or more & like on folder path being C:\Temp\Development & Test which is interpreted by cmd.exe outside a double quoted argument string as a command operator explained in detail on single line with multiple commands using Windows batch file.
The perfect command line is as follows after making sure the command extensions are enabled and delayed environment variable expansion is disabled:
set "NODE_HOME=%~dp0nodejs"
An ampersand in full path of batch file is interpreted here as literal character in double quoted argument string of command SET.
It is important on writing a batch file how a command line looks after Windows command processor parsed it and replaced all environment variable, loop variable and batch file argument references and not how the command line is written in batch file. This command line does not contain an & in batch file, but it can contain & on execution of the command line after replacing %~dp0 by full path of batch file.
It is possible to see how the command line looks after parsing by cmd.exe by running a batch file from within an opened command prompt window with #echo off removed or commented out temporarily to get displayed also the command lines finally executed.
3. Correct modification of local environment variable PATH
set PATH=%NODE_HOME%;%PATH% is again not good as it results in undefined behavior if the string assigned to either environment variable NODE_HOME or environment variable PATH contains an ampersand. The perfect and safe command line (on valid PATH string) would be:
set "PATH=%NODE_HOME%;%PATH%"
4. Referencing executables and scripts with full qualified file names
It is always best to reference executables and scripts in a batch file with full qualified file name on being well known instead of just file name as in this case cmd.exe does not need to search for the file in current directory and all directories listed in local environment variable PATH for a file with an extension listed in local environment variable PATHEXT.
Please take a look on answer on What is the reason for "X is not recognized as an internal or external command, operable program or batch file"? for details.
A batch file referencing executables and scripts with full qualified file names works also on PATH corrupted somehow by an installer or a user, and works also if there are (mainly batch) files created with a file name identical to a Windows command which is used in the batch file, but found by chance by cmd.exe instead of the executable in %SystemRoot%\System32.
So with batch file npm.cmd stored in subdirectory nodejs of batch file directory it would be better to use as replacement for the last three command lines:
call "%NODE_HOME%\npm.cmd" install
call "%NODE_HOME%\npm.cmd" start
start "" "http://localhost:8090/"
5. No need for an additional batch file
It is unclear why another command processor instance is started running parallel to the cmd.exe instance processing the batch file after calling batch file npm.cmd with argument install which is processing one more batch file which runs %SystemRoot%\System32\timeout.exe (without file path and file extension) to wait five seconds and then launch default internet browser with a local url as argument as separate process resulting in second started instance of cmd.exe terminating itself.
It should be enough to call npm.cmd with argument start and start default internet browser as separate process with local url as argument after processing of npm.cmd with argument start finished.
So the entire batch file could be:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "NODE_HOME=%~dp0nodejs"
set "PATH=%NODE_HOME%;%PATH%"
call "%NODE_HOME%\npm.cmd" install
call "%NODE_HOME%\npm.cmd" start
start "" "http://localhost:8090/"
It could be that call "%NODE_HOME%\npm.cmd" start results in starting an application as separate process or a service which takes some time to initialize completely and for that reason some seconds must be waited before the internet browser is started with the local url which requires that the started application/service is running already. In this case the batch file should be:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "NODE_HOME=%~dp0nodejs"
set "PATH=%NODE_HOME%;%PATH%"
call "%NODE_HOME%\npm.cmd" install
call "%NODE_HOME%\npm.cmd" start
%SystemRoot%\System32\timeout.exe /T 5 /NOBREAK >nul
start "" "http://localhost:8090/"
It does not look so according to posted information posted, but in case of call "%NODE_HOME%\npm.cmd" start results in cmd.exe processing the batch file terminates itself because of a command exit without option /B before reaching end of batch file or the processing of the called batch file never finishes because of cmd.exe is waiting for self-termination of a started executable which does not terminate itself, the batch file should be:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "NODE_HOME=%~dp0nodejs"
set "PATH=%NODE_HOME%;%PATH%"
call "%NODE_HOME%\npm.cmd" install
start "Launch browser delayed" /MIN %ComSpec% /C %SystemRoot%\System32\timeout.exe /T 5 /NOBREAK >nul & start "" "http://localhost:8090/"
call "%NODE_HOME%\npm.cmd" start
There is no additional batch file needed in any case.
6. Keep command processor running after finishing execution of batch file
Windows executes implicit %ComSpec% /c "Full qualified batch file name" on double clicking a batch file with making the batch file directory the current directory for cmd.exe. The help output on running in a command prompt window cmd /? explains that option /C is for running a command line and close cmd.exe after finishing execution of this command line. This default behavior is not wanted here. The command processor should keep running after batch file execution which requires starting cmd.exe with option /K and the full qualified batch file name.
Therefore a shortcut file (.lnk) file needs to be created on Windows desktop or in Windows start menu or somewhere else and pinned to Windows taskbar which contains in properties:
Target: %SystemRoot%\System32\cmd.exe /K "Full qualified batch file name"
Start in: "Full path of batch file folder"
The property Target can be also:
%ComSpec% /K "Full qualified batch file name"
ComSpec is a system environment variable used even by cmd.exe itself and must be defined always with %SystemRoot%\System32\cmd.exe as it is by Windows default.
In properties of the shortcut file can be configured also the number of lines and columns for the console window opened on running cmd.exe via this shortcut, the font, the text foreground and background colors and much more. It is even possible to define a Shortcut key to launch cmd.exe for processing the batch file from within any application by pressing this key (or combination of keys).
I am learning both nodeJS and batch scripting and I would like to get the node version using a batch script.
Current code is this:
FOR /F "tokens=* USEBACKQ" %%F IN (`node --version`) DO (
SET NODE_VER=%%F
)
ECHO %NODE_VER%
pause
But I do not understand why this doesn't work. It just freezes after calling command node --version. I also tried calling node -v but same behavior. This exact command works when replacing node --version with python --version. Help!
cmd commands will always first read the local directory for a matching command, then it will go to the environment %path% to search for the command. In this instance, Node exists inside of the %path% variable, but you also have a node.??? file in the local directory and will therefore be used. Therefore the following measures are important:
Never name batch files the same as executables. i.e use my_node_script.cmd
Always try and use the full executable name inside of the batch file node.exe --version and if possible rather use the full path to the executable, should you require a duplicate name such as node inside your working directory. Something like:
"C:\Program Files\nodejs\node.exe" --version
or
"%ProgramFiles%\nodejs\node.exe" --version
Try this:
#ECHO OFF
FOR /F %%F IN ('node.exe --version') DO ECHO %%F
PAUSE
GOTO :EOF
I need to execute a Babun script with Windows Scheduler on Windows Server 2003, the problem is: How can I execute a script in Babun shell from a .bat or similar?
The script is a really simple one line rsync command.
Here is the Babun reference.
first copy .babunrc to .babun_scheduler_rc and add one line export PATH="/usr/bin:$PATH"
The location of .babunrc is: C:\Users\user\.babun\cygwin\home\user you can edit it from babun too.
next create the script.bat:
#echo off
setlocal enableextensions enabledelayedexpansion
set SCRIPT_PATH=%~dp0
set SCRIPT_PATH=%SCRIPT_PATH:\=/%
set BABUN_HOME=%SCRIPT_PATH%
set CYGWIN_HOME=%BABUN_HOME%\cygwin
set BASH=%CYGWIN_HOME%\bin\bash.exe
"%BASH%" -c "source ~/.babun_scheduler_rc && rsync -Crav /cygdrive/c/Path/To/Copy user#remote:/tmp/path/to/copy"
and now you can add it to the scheduler.
I am attempting to write a simple batch file to build a gulp project and a maven project.
The current file follows:
cd C:\my\file\path
cmd /k gulp maven-deploy-local
cd C:\my\file\path\two\project-pom-parent
cmd /k mvn clean install -Dmaven.test.skip=true
Whenever I run this script, the command line stops after line 2 and before line 3. I end up looking at this line in cmd with a blinking cursor:
C:\my\file\path>
If I run the file without the cmd /k (as follows) then the prompt simply closes after line 2 and before line 3.
cd C:\my\file\path
gulp maven-deploy-local
cd C:\my\file\path\two\project-pom-parent
mvn clean install -Dmaven.test.skip=true
How can I modify the batch script so that it will continue and execute the commands on lines 3 and 4 and then remain open with the following line and blinking cursor?
C:\my\file\path\two\project-pom-parent>
I am operating on Windows 7 64-bit
This task is specific enough to use this as well:
cd /d "C:\my\file\path"
cmd /c gulp maven-deploy-local
cd /d "C:\my\file\path\two\project-pom-parent"
cmd /k mvn clean install -Dmaven.test.skip=true
In essence the first cmd /k can be changed to cmd /c so it executes the command and continues to the last command, which leaves the prompt open.
#ECHO OFF
IF NOT "%1"=="1" CMD /K ""%~f0" 1"
CD /d C:\my\file\path
CALL gulp maven-deploy-local
CD /d C:\my\file\path\two\project-pom-parent
CALL mvn clean install -Dmaven.test.skip=true