If I make a file foo.exe, and it contains the files bar.bat, baz.bat, and qux.bat, can I call baz.bat from within bar.bat? I mean, if bar.bat is the file that is executed upon execution of foo.exe?
I had done something similar using winrar (instead of iexpress) self extracting archive.
The mechanism is like below:
First it will extract everything to specified folder (or in temporary folder %TEMP%/random_name)
Then it will call initial executable/script or "script to run after extraction". In your case, it's bar.bat.
That executable script can in turn call any other script/executable. (baz.bat in your example)
To be sure, change the file bar.bat to contain below script:
#echo off
cd
explorer .
pause
This will print the directory name, where it has extracted & open the directory with explorer.exe. Then you can verify that your baz.bat is in same directory. Give relative path, if required.
Related
Currently this is how I have written the code in the batch file:
C:\ cd C:\abc\xyz\build-scripts-master
call setEnv.cmd
cmd ant do-clean
cmd ant do-dist
This is not working. It just executes the setEnv and breaks out. It does not run the remaining commands
Manually this is how it works:
I first go to the folder C:\abc\xyz\build-scripts-master through the Command Prompt
Then I type in setEnv, which is a windows command script, and hit return.
Then I type in ant do-clean
And then ant do-dist
I want to automate this process and hence was trying to achieve this using batch file.
Try the following:
#CD /D "C:\abc\xyz\build-scripts-master"
#Call setEnv.cmd
#Call ant.bat do-clean
#Call ant.bat do-dist
The latter two lines assume that ant.bat is located somewhere in the current working directory or %PATH%
It is not imperative that the directory path is doublequoted in this case, just good practice.You could continue not to use the .bat extension with ant. I've included it just to make it clear that it is a batch file, and should be Called in the same way as the setEnv batch file.
it didn't run the bat files because you didn't specify the files' location in the code. As it stands right now, the script expects the .bats to exist in the working directory or it has been placed in the folder. The only way it will run the files arbitrarily is if you had placed your working location in the system variables or set the Path to the folders location. I don't know if the cmd and call are needed. I have never used them in my scripts.
I may be confusing current directory with working directory but regardless I am trying to make a batch file that runs the tree command from the folder it's currently in.
I have a folder called "Network_Switch_Backup" with a script, some other items and a subfolder called "backups".
This has worked for testing purposes:
tree U:\Desktop\Network_Switch_Backup\backups /f
But as I will be zipping it and sending it to different computers and users clearly this isn't practical since they could put the folder anywhere besides the desktop.
I've looked at other threads and amongst other things I tried, this looked the most promising (but still did not work):
tree %cd%\backups /f
However tree %cd%\downloads /f works perfectly fine when running from cmd so I'm just a bit confused.
It is advisable in batch files to reference executables to run with full qualified file name which means full path + file name + file extension, especially if the storage location of the executable is well known. That makes the batch file independent on the values of the environment variables PATHEXT and PATH. PATH is quite too often not correct defined on many computers running Windows.
The full qualified name of TREE is %SystemRoot%\System32\tree.com.
Environment variable SystemRoot is not defined as system or user environment variable like PATH and PATHEXT, but is nevertheless defined on execution of a batch file. So it is very safe to use this Windows environment variable.
What is the reason for '...' is not recognized as an internal or external command, operable program or batch file? explains very detailed how Windows command processor finds executables and scripts not specified with full qualified file name on command prompt or in a batch file.
There are two directories which need to be taken into account on coding an application or script:
The application/script directory is the directory containing the program or script.
The current directory or working directory is the directory from which the program or script is executed.
For example a batch file is stored in directory "%UserProfile%\Desktop". Windows sets the directory of the batch file as current directory on simply double clicking the batch file on user's desktop. Therefore the script directory is the current directory on execution of the batch file. But if this batch file is executed by right clicking on the batch file and left clicking on context menu option Run as administrator, the batch file stored in "%UserProfile%\Desktop" is usually executed from directory %SystemRoot%\System32 depending on user account permissions and on user account control setting of current user. The reason for making %SystemRoot%\System32 the current directory before executing the batch file is explained in detail by answer on Why does 'Run as administrator' changes (sometimes) batch file's current directory?
The MSDN article Naming Files, Paths, and Namespaces explains in detail how to reference files and folders relative to current directory. The current directory is simply not included in file/folder argument string or alternatively represented by .\.
In case of drive and path of current directory needs to be known, for example to output it on running a batch file, there is the dynamic environment variable CD (short for Current Directory). %CD% or !CD! with delayed expansion enabled expands to full path of current directory which does not end with a backslash, except the current directory is the root directory of a drive. The help output on running in a command prompt window set /? explains dynamic environment variable CD briefly on last help page.
Batch files need to be designed very often to reference files or folders with a path relative to directory of the batch file. In this case it is not advisable to use the current directory because the current directory can be really any directory.
The help output on running call /? in a command prompt window explains how arguments of a batch file can be referenced from within a batch file. Argument 0 is always the batch file itself.
%~dp0 references drive and path of the batch file. This file path ends always with a backslash, but of course can contain a space or one of these characters &()[]{}^=;!'+,`~ which require entire file/folder argument string to be enclosed in double quotes. So %~dp0 must be concatenated in a batch file without an additional backslash after that string and the entire argument string must be enclosed in double quotes to work safely.
So the command line to use to reference the subdirectory Backups in directory of the batch file independent on which directory is the current directory is:
%SystemRoot%\System32\tree.com "%~dp0Backups" /F
A bug of cmd.exe explained in detail on What is the reason for batch file path referenced with %~dp0 sometimes changes on changing directory? should be taken into account on using %~dp0 in a batch file.
I have one batch file that suppose to call another. I read that call command is used in this case. Although error message appears:
The system cannot find the path specified.
The path is not wrong 100% sure. This is the caller run.bat
#echo off
call xslt\projects\asp-bus\implementation\batch\ant-start.bat
pause
and this is the called ant-start.bat
set ant="../../../../infrastucture/apache-ant-1.10.0/bin/ant.bat"
call %ant%
pause
In each batch file, the paths are relative to the working folder you are running the batch file from, not the folder that contains the batch file itself. You either need to use absolute paths (e.g. starting with C:\), or to make sure that when each batch file is run from a working folder where the relative paths make sense.
If you're launching run.bat from a Windows shortcut, you can set the "Start In" folder from the shortcut's Properties dialog. When ant-start.bat is called, it will run from the same folder as run.bat.
To fix the problem, you might need to change ant-start.bat to
set ant="infrastucture/apache-ant-1.10.0/bin/ant.bat"
call %ant%
pause
Alternatively, you could put a cd command in one of the batch files, to force it to use an appropriate working folder.
Bear in mind that if you set the %ant% variable to a relative path as above, using the variable will only work from a folder where that relative path makes sense.
I am writing a batch file on my Windows 8.1 machine. In one section of my batch file I need to start a command prompt in the "current working directory".
So far, this is what my batch file looks like:
#echo OFF
set WORKING=%cwd%
start cmd.exe /K pushd %WORKING%
exit
Let's say the batch file is located in the folder C:\Temp\Utilities. If I open an explorer window and double click the batch file to run it everything works great. A new command prompt is created in the directory C:\Temp\Utilities. However, if I right-click the batch file and select Run as administrator the working directory is no longer the location of the batch file, it's C:\Windows\System32.
Similarly, if I create a shortcut to the batch file in a different folder (for example. C:\Temp) and repeat the two steps above the results are the same. If I double click the shortcut and run it as a normal user the working directory is what I would expect. (Note, the working directory for the shortcut it's whatever is set for "Start in" of the shortcut properties, not the location of the batch file.) If I right click the shortcut and run it as administrator I again get a command prompt opened to the folder C:\Windows\System32.
I assume this is a "bug" or "feature" (if you want to call it that) in Windows 8.1 and it probably happens because execution environments for programs run as administrator are forced to run in the System32 folder? (I remember with Windows 7 this did not happen so it must be a new feature to Windows 8.)
I found one way to fix the issue and stop the command prompt from starting in C:\Windows\System32. I did this by modifying the following line in the batch file:
set WORKING=%~dp0
Doing it this way sets the working directory to the location of the batch file. With this change, no matter how I run the batch file or the shortcut (administrator or normal) the working directory ends up being the same, C:\Temp\Utilities.
The problem with this solution is I don't want the working directory to always be the location of the batch file. If the batch file is run directly then it's okay but if I run it from a shortcut I need the working directory to be whatever is set in the "Start in" property of that shortcut. For example, if the batch file is located in the folder D:\Temp\Utilities this is what I need to happen regardless of whether I run as administrator or not:
Shortcut Location Start In Property Command Prompt Working Directory
-------------------- ------------------- ------------------------------------------
C:\Temp <undefined> D:\Temp\Utilities
C:\Data\bin C:\Data\bin C:\Data\bin
C:\Data\bin D:\Temp\Utilities D:\Temp\Utilities
What this means is I can't always use %~dp0 to set the working directory in my batch file. What I need is some way for the batch file to know if it was run either directly or by a shortcut. If the batch file is run directly then the working directory is easy to get, it's just the value of %cwd%. If the batch file is run by using a shortcut, I don't know how to get the "Start in" property inside the batch file.
Does anyone know how I can do these two things inside my batch file:
1. Check whether it was run directly or by a shortcut.
2. If run by a shortcut, get the "Start in" property of the shortcut that started it.
Thank you,
Orangu
UPDATE
I found sort-of a "hackish" way to fix the issue. For the shortcut I edited the "Target" field and changed it to the following:
cmd.exe /k pushd "C:\Temp" && "D:\Temp\Utilities\batchfile.bat"
Now the working directory can be obtained by calling %CD% in the batch file and this works for both administrator and normal users. It does not, however, work for the case when I run the batch file directly. I still need to use %~dp0 in that case.
I don't like this solution, however, because it requires me to manually change all shortcuts I make and it also makes the icon look like a cmd prompt icon rather than a batch file.
Have you already considered to not use shortcuts at all?
You could e.g. create a batchfile_exec.bat containing your call
REM optionally do
REM cd /D working_directory
REM if you want to force a special working directory
D:\Temp\Utilities\batchfile.bat
and replace all the shortcuts with batchfile_exec.bat. If you double-click batchfile_exec.bat, the working directory will be the one containing batchfile_exec.bat.
I personally don't like Windows shortcuts that much, because they are hard to handle within a revision control system. As you also noticed, it is very time consuming if you want to modify a lot of them.
By the way: If batchfile.bat was designed/written to be always run from the direcory where it is located, you might also consider to modify batchfile.bat to force that behaviour:
setlocal
cd /D %0\..
REM your original content
endlocal
In %0 the path to the batchfile is stored.
The trick is to assume that %0 is a directory and then to change one level lower based on that directory. With /D also the drive letter is changed correctly.
The cd command doesn't care if %0 is really a directory. In fact %d doesn't even have to exist (%0\dummy\..\.. would also work).
The setlocal command is to have the working directory being restored when batchfile.bat has finished (this would be good if batchfile.bat was called form another batch file).
I noticed that the endlocal command is not really necessary in this context since it is applied implicitly when batchfile.bat finishes.
Consider a directory structure containing the following files:
\1.3\Baseline\GeneratedScripts\One\FullInstall.cmd
\1.3\Baseline\GeneratedScripts\Two\FullInstall.cmd
\1.3\Baseline\GeneratedScripts\Three\FullInstall.cmd
\1.3\Patches\Patch1\GeneratedScripts\One\FullInstall.cmd
\1.3\Patches\Patch1\GeneratedScripts\Two\FullInstall.cmd
\1.3\Patches\Patch1\GeneratedScripts\Three\FullInstall.cmd
\1.3\Patches\Patch2\GeneratedScripts\One\FullInstall.cmd
\1.3\Patches\Patch2\GeneratedScripts\Two\FullInstall.cmd
\1.3\Patches\Patch2\GeneratedScripts\Three\FullInstall.cmd
\1.3\Patches\Patch3\GeneratedScripts\One\FullInstall.cmd
\1.3\Patches\Patch3\GeneratedScripts\Two\FullInstall.cmd
\1.3\Patches\Patch3\GeneratedScripts\Three\FullInstall.cmd
I would like to construct a Windows batch file InstallEnvironment.cmd which:
Takes an environment name as a parameter; then
Executes the baseline install script, and each of the patch scripts in turn.
The batch file should automatically execute any additional patches that are added later.
Essentially I need to do something along the lines of this:
for %%_ in (1.3\**\GeneratedScripts\%%1\FullInstall.cmd) do cal %%_
However I'm not sure the wildcard system is rich enough to allow this as I don't get any matches for the ** directory wildcard.
For example, calling with the parameter "Two" should execute the following scripts, in order:
\1.3\Baseline\GeneratedScripts\Two\FullInstall.cmd
\1.3\Patches\Patch1\GeneratedScripts\Two\FullInstall.cmd
\1.3\Patches\Patch2\GeneratedScripts\Two\FullInstall.cmd
\1.3\Patches\Patch3\GeneratedScripts\Two\FullInstall.cmd
This will execute all the *.cmd files in the sub folders based on the argument:
for /r 1.3\ %%X in (GeneratedScripts\%1\*.cmd) do call "%%X"
In my experience, the %1 substitution works within directory names.
This should work:
InstallEnvironment.bat:
\1.3\Baseline\GeneratedScripts\%1\FullInstall.cmd
\1.3\Patches\Patch1\GeneratedScripts\%1\FullInstall.cmd
\1.3\Patches\Patch2\GeneratedScripts\%1\FullInstall.cmd
\1.3\Patches\Patch3\GeneratedScripts\%1\FullInstall.cmd
Edit this batch file to add additional patches in order, and it works. If you need to run the same batch file on multiple directories, create another batch file:
call InstallEnvironment.bat %1
call InstallEnvironment.bat %2
If you want to run a batch file in the background, use a vbs file to run that bat file in background instead.
Here is the code:
CreateObject("Wscript.Shell").Run"""" & Wscript.Arguments(0)& """",0,False
Save this exactly as invisible.vbs (or anything) and then make another batch file which will call your batch file to run it in background.
The code for the second batch file is:
wscript.exe "invisible.vbs" "Your_Batch_File.bat"
Then run the second batch file.
Note: WSH should be enabled on your computer, and the invisible.vbs file and the second batch file should be in the same folder. If not then you can give the full path to the invisible.vbs file in the 2nd batch file's script.