I have a very simple problem:
call myBatch.bat "K:\dir name with spaces\eatThis.xml"
Which will not work, it will stop with
K:\dir does not exist
Could you please point me to the SO question addressing such an issue? I've already dug myself through quite a lot of SO questions regarding batch files and whitespaces in parameters but I guess the solution to my problem must have been ignored accidentally.
--
OK, after some debugging it turned out that it was not the batch file that was faulty but the Java application that invokes String.split(" "); to separate multiple arguments from each other. So when one argument contains a space, in its path, the application logic falls apart. As the original question no more describes what the real problem is, shall I rewrite it completely or write a new one? Anyway, my bad, feel free to downvote is.
I created the following mybatch.bat and started it with call myBatch.bat "K:\dir name with spaces\eatThis.xml" Output is:
"K:\dir name with spaces\eatThis.xml"
Mybatch.bat:
echo off&setlocal
echo "%~1"
Related
I need help with understanding the following Batch script structure:
This is named Profile_something_schedule.bat
call somePath\lib.cmd :someLabel reqPath
call somePath\lib.cmd :someLabel reqKey
%reqPath% "%~someFileName" /vv_pwd=%reqKey% /bProfile_something_schedule /min
I have a lot of difficulty understanding why this script works.
I do not know why the 3rd line is valid. The behavior produced is that the someFileName is run. I understand it as starting the file as a process. Then why isn't the start command needed? I don't see any batch documentation saying you can simply run a file by writing its pathed filename.
I do not understand the syntax of "%~someFileName". From online searching about it almost every source shows you the batch call parameter table, saying things like %~1 expands %1..., %~f1 expands %1 some other way, etc. All of them involve some kind of number from 0 to 9 to correspond to the parameter position. However, I cannot find any specification of %~someString being legal. There is no parameter positional information from the someFileName string, it is a filename.extension string. Still, it is quite likely this line is trying to run this format.
What does "/vv_pwd=%reqKey% /bProfile_something_schedule" mean? In the lib.cmd that was called previously, there were variables reqPath and reqKey and I am quite certain it is trying to pass the value of reqPath and reqKey from the lib.cmd into the variables here and then I guess it is trying to use the reqKey value as a parameter, which is a password required to run the file.
Inspecting the file, it contains some script of some paid software specific format, it only has variable name v_pwd inside but not vv_pwd. I do not know what the /bProfile_... is for. The part without the /b is exactly this batch file's name. But together with the /b I don't know what it means. The /v and /b look like some kind of options to me but I cannot see any specification explaining as there is no command beginning line 3 just some path. I guess the /min option refers to starting window minimized which is an option for the command start, yet there is no option of /v. The /B in start means to start application without creating window, which is quite unnecessary to have /min if you are not going to create a window in the first place. And it doesn't make sense to use /B directly followed by some string of Profile_something_Schedule.
FYI, the lib.cmd starts with call %*, which I would consider as trying to call all passed parameters and assuming those parameters are actually batch files that can be called.
Another thought I have is that the 2nd line call connects with the 3rd line so the 3rd line may not need a command. But I can't make sense of it. The someFileName is not of the Batch extension so I doubt it can be called as the call doc says it is for batch programs. If I want to run non-batch programs I need to use start right?
Would greatly appreciate your help!
The variable pathext contains a semicolon-separated list of executable filenames that may be appended as an extension to myexecutable. if the first string on a batch line is not a cmd internal command (like set, for etc.) then cmd tries to find myexecutable + each of the extensions in pathext in turn, first in the current directory, and then in each directory in the path (another semicolon-separated list of directories) and runs the first name found, or fails if none are found. That first string may also have an Associated extension, which then runs the application with which the extension is associated (like .txt runs notepad by default)
Neither do I, and I can't see that even knowing what the actual strings being executed by %reqPath% are would assist. See for /? from the prompt for more documentation on other ~ operators - or search SO for thousands of uses.
vv_pwd=%reqKey% : %reqKey% is replaced by the value of the variable reqKey evidently returned by the previous line. / is used in Windows to mean "here's a switch parameter for the executable", so evidently /vv_pwd=[the contents of reqKey], /bProfile_something_schedule and /min mean something to the executable %reqPath%. Quite what is anyone's guess.
The fact that lib.cmd's first line is call %* would mean that lib.cmd contains a library of routines. Since each call you have shown is of the form :string1 string2 then the resultant command executed would be call :string1 string2. call :string1 will call the routine contained within "lib.cmd" with the label string1: supplying string2 (and presumably optionally string2 string3... as parameters. Evidently, string2 is the name of the variable into which lib.cmd places the required data.
Without the :, string1 would be any executable that cmd can locate using the method in (1). It does not have to be a batch, but commonly is a batch.
I have a requirement to execute a batch file with the arguments. the problem occuring here is I am not sure what special characters and at what place it can occur. I have gone through possibly all the answers here but still unable to fix the issue. Any help is appreciated.
Command that i am trying to run within the batch file
CALL E:\myscript.bat -run e:\param -password %PASSWORD%
where PASSWORD is the variable storing the password and it can be having any special characters at any position.
Maybe I understood your question, it would be:
You want to identify, without having to have specific argument
positions, what each argument represents.
Or:
You want to find a solution to handle the arguments so that they do
not result in errors because they contain special characters
Anyway, I will answer both.
You have some alternatives for doing so, some may be more ideal than others depending on how you are handling your code and its purpose.
In case you identify the arguments and what they represent, you can:
set args=%*
Some things may help you make your code stable while using an wildcard without its effect. Like:
set "args=%args:&=^&"
But the most important thing is to keep the code without quotes. In fact, the use of CALL is not necessary if you are not doing it within a script.
set "args=%args:"=%
The next thing to do is to identify the parameters. We can do this both in a crude way and in a simpler way, which would be defining each argument with its own variable, such as: arg1=%1, arg2=%2...
You can now pass all parameters into a treatment and reconstruction session.
Assuming you want to identify -password:
---during a FOR loop to catch and make the same processes at every arg---
(which I can only guess because you didn’t show the code or anything like that)
if "!arg[%%x]:~0,1!" equ "-" (
if "!arg[%%x]:-=!" equ "password" set /a x=%%x+1&set "password=!arg[%x%]!"
if "!arg[%%x]:-=!" equ "run" set /a x=%%x+1&set "run=!arg[%x%]!"
...
)
Obviously there are some things that can improve in this code, but you have shown almost nothing for us to use as a reference to answer, so that's all I can do.
Hope this helps,
K.
I have a batch file that calls a VB Script file. This VB Script comes from MS Office Suite and is located in the Installed Folder. My file calls the VB Script and pipes it to a file using the > symbol. This works if your redirect is a string. I was wondering how to redirect to a file using a variable.
I'm only including a small fraction of the code showing how I want it to work.
This, as written, works. However I want my batch file to use a variable instead of the text in quotes. In fact, my batch file creates the path depending on where the batch file is located.
::Create file and display on screen
Echo Writing Information to File: "OfficeStatus.txt"
Call cscript ospp.vbs /dstatus > OfficeStatus.txt
Echo.
When written as shown below, it does not work:
::Create file and display on screen
Echo Writing Information to File: "OfficeStatus.txt"
Call cscript ospp.vbs /dstatus > %_sLogFile%
Echo.
I don't know if the issue is because of the redirect not able to handle a variable or not. An example of what might be in the variable:
_sLogFile=E:\UserName\Documents\Status\OfficeStatus.txt.
Any thoughts would be great.
The variable, by the way, correctly contains the path and filename... so that's not the issue.
it does not work means did not do what I expected and unfortunately does not tell us what it did do.
Did it crash the system? Create an error message (If so, what message)? Create an output file in an unexpected place??
Personally, I'd suspect what you have concealed as username. Without knowing precisely what that text is, we start guessing, which isn't a logical approach. It doesn't have to be the real username, substitute Fred Bloggs for the real name to mask it if necessary.
I believe that username may either be %username% to retrieve the name from the system, or a real literal. The problem with this is that such names often contain spaces, you'd need to "Enclose the full filename in quotes".
See - had you told us _sLogFile=E:\Fred Bloggs\Documents\Status\OfficeStatus.txt it would all have been a lot clearer - presuming that my guess as to the cause of the problem is correct.
Perhaps you should look for files named like E:\Fred which is where the expected output may have ended up.
Assume I want to permanently append the following list of directories (in a trimmed version for the sake of simplicity) to my system (as opposed to my local) PATH environment variable.
c:\company\dept\users
d:\school\teachers
e:\school\students
I have to do this by clicking a batch file (with admin privilege set on). If I am not sure I have already done it, I can do clicking the batch file again but without appending redundancies.
Shortly speaking, how can we write such a batch file? I guess we have to make a test for each item in the list whether or not it has been in the PATH. But how to do this?
What I have done so far is
setx PATH "%PATH%;c:\company\dept\users" /m
setx PATH "%PATH%;d:\school\teachers" /m
setx PATH "%PATH%;e:\school\students" /m
but it is not intelligent to prevent redundancies.
I have no knowledge to implement the redundancy test.
As a general approach, I would suggest looking at for with a delims=; to split %PATH% on semicolons, then compare each part to the path you're considering adding.
If you have specific problems along the way, post them as new questions (or search--they may already be answered) and we'll be happy to answer more.
You can get documentation on the for loop by typing help for at the command line.
EDIT: Here's a better answer, from the SuperUser forum: Append to path without duplicating it
If from inside a bat file you called another batch file but still had a few remaining operations to complete, how can you make sure that the call to first bat file will after completion or error, will return to the file that called it in the first instance?
Example:
CD:\MyFolder\MyFiles
Mybatfile.bat
Copy afile toHere
or
CD:\MyFolder\MyFiles
CALL Mybatfile.bat
COPY afile toHere
What is the difference between using CALL or START or none of them at all? Would this have any impact on whether it would return for the results of the copy command or not?
As others have said, CALL is the normal way to call another bat file within a .bat and return to the caller.
However, all batch file processing will cease (control will not return to the caller) if the CALLed batch file has a fatal syntax error, or if the CALLed script terminates with EXIT without the /B option.
You can guarantee control will return to the caller (as long as the console window remains open of course) if you execute the 2nd script via the CMD command.
cmd /c "calledFile.bat"
But this has a limitation that the environment variables set by the called batch will not be preserved upon return.
I'm not aware of a good solution to guarantee return in all cases and preserve environment changes.
If you really need to preserve variables while using CMD, then you can have the "called" script write the variable changes to a temp file, and then have the caller read the temp file and re-establish the variables.
call is necessary for .bat or .cmd files, else the control will not return to the caller.
For exe files it isn't required.
Start isn't the same as call, it creates a new cmd.exe instance, so it can run a called batch file asynchronosly
The `CALL' statement was introduced in MS-DOS 3.3
It is used to call other batch files within a batch file, without aborting the execution of the calling batch file, and using the same environment for both batch files.
So in your case the solution is to use CALL
Okay, I actually didn't even really think about the fact that if you call a batch (regardless of the 'type', i.e. '.bat', or '.cmd') that it won't return if you don't use call.
I've been using call myself though for a different reason that I am actually pretty surprised that no one else has brought up. Maybe I missed it. MAYBE I'M THE ONLY ONE IN THE WORLD WHO KNOWS!! :O
Probably not, but I'm going to drop this knowledge off here because it's super useful.
If you use call you can use binary logic operators to decide how to proceed based on the ERRORLEVEL result. In fact, I always was flabbergasted on how && and || existed in DOS and COULDN'T be used this way. Well, that's why.
The easiest way to test this is to create a return.cmd with notepad, or from the command prompt like so:
c:\> type con >return.cmd
You will now notice the cursor goes down to the next line and hangs. Enter:
#exit /B %1
And then hit ENTER, and then CTRL-Z and that file will be created. Good! You may now feel free to try the following two examples:
call return.cmd 0 && echo Huzzah! A Complete Success! (Or cover up...)
call return.cmd 123 || echo Oops! Something happened. You can check ERRORLEVEL if you want the tinest amount of additional information possible.
So what? Well, run them again with the 0 and the 123 swapped and you should see that the messages DON'T print.
Maybe this multi-line example will make more sense. I use this all the time:
call return.cmd 0 && #(
echo Batch says it completed successfully^^!
) || #(
echo Batch completed, but returned a 'falsey' value of sort.
call echo The specific value returned was: %ERRORLEVEL%
)
(Note the 'call' in the || section before the second 'echo'. I believe this is how people got around not having delayed expansion back in the day. If you DO have delayed expansion enabled (via. setlocal EnableDelayedExpansion inside a batch OR launch a command prompt with cmd /v:on then you can just do !ERRORLEVEL!.)
... This is where I have to apologize and say if you have if ERRORLEVEL trauma in your past you should stop reading. I get it. Trust me. I thought about paying someone on fiverr to remotely type this for me, but for completeness sake I'm just going to take one for the team and mention that you can also do the following to check errorlevel:
if ERRORLEVEL 123 #echo QUICK! MOTHERS, COVER YOUR CHILDREN'S EYES! FINGERS ARE BEING UNDONE! :'(
If you've never typed that before then GOOD! You will live longer without having to read up why exactly you aren't getting the results you expect. Cruel is the word you're looking for, not 'quirky'.
The important part that I really want to get across however is that if you try this and DON'T use 'call' it will ALWAYS execute the 'true' branch. Try it for yourself!
If I'm missing something, or you know a better way to do this, please let me know. I love learning stuff like this!
Additional information I mentioned:
I have known for quite some time that you can put redirects BEFORE commands like so:
>nul echo. This won't be displayed!
But I accidentally discovered the other day by being a dumdum that you can apparently also do:
echo A B>file.txt C
And was REALLY surprised to find a file.txt which consisted of "A B C". It appears yo can place them ANYWHERE, even inside the command. I've never seen anyone do this, nor mention it, but I HAVE seen people mention that you can prefix a line with them.
Maybe it's a bug exclusive to Windows 10 or something. If you have another version and wanna try it out and let me know I'd be interested in what you find out.
Stay nerdy!