starting a bat script from bash under windows - windows

I am trying to start a .bat file from gow bash. I can sucessfully start a batch and return to bash with the following (I am in C:\tmp\a\ directory), the content of the file a.bat file consists a single command cd (to print the current working directory):
$ cat a.bat
cd
$ cmd "/C a.bat"
c:\tmp\a>cd
c:\tmp\a
$
Now if I try to start the program from c:\tmp (one level higher in the hierarchy of directory structure), I get an error:
$ cmd "/C a\\a.bat"
'a' is not recognized as an internal or external command,
operable program or batch file.
$ cmd '/C a\a.bat'
'a' is not recognized as an internal or external command,
operable program or batch file.
$ cmd '/C a/a.bat'
'a' is not recognized as an internal or external command,
operable program or batch file.
How can I start a batch script given a path to it, and return to bash?

I guess I found a very simple solution:
Add a dot before /C
cmd ". /C a\a.cmd"
After that gow (and cygwin and alikes) stop treating the argument as containing paths and converting it to POSIX paths.
And cmd ignores everything up to /C (well, almost everything, I think).
a.cmd:
#echo off
echo it's working
output:
bash-3.1$ cmd ". /C a\a.cmd"
it's working
bash-3.1$
[Update]
After some research I found that POSIX path conversion has a very clean description of conversion rules.
In your case the rule An argument with a leading / is converted up to the first /.. seems to be applied.
Conversion results in changing '\' to '/'. So, you get a/a.cmd, that is a with a switch /a.cmd. And this results in the observed error, of course.
The link above addresses MSYS and seems to be a bit outdated, but I've checked some of the rules in bash from my fresh Git for Windows installation (based on MSYS2), and they look working as described.

After a bit of research and posting questions to other forums I found the following additional info to run the job "correctly":
cmd //D . //C "a\a.cmd"
References:
Github issue #244, Unix to Windows path translation may corrupt command switches/arguments
Github issue #243, when bash starts a cmd, it adds a buggy double quote symbol at the end of the line

Related

Windows batch file: pathname with "&" interpreted as two commands

I have a batch file which gets its own short pathname (to eliminate spaces, which gcc doesn't like) for use in subsequent commands:
set base=%~d0%~sp0
This works fine for most cases; for example, if the batch file is located in C:\Program Files, the value of %base% will be C:\PROGRA~1, and gcc is happy.
However, it doesn't work if the batch file is in a directory with "&" in the name. If it is in a directory called "C:\Here & There", the command above expands to
set base=C:\HERE&T~1\
which is treated as two commands, producing the error message 'T~1\' is not recognized as an internal or external command, operable program or batch file.
If I put quotes around it:
set base="%~d0%~sp0"
Then the command works, and the value of %base% is "C:\HERE&T~1\" (including the quotes). But then the quotes break something else further on in the file when I use it to build a Java classpath:
java -cp .;"C:\HERE&T~1\"Jars\* foo
which says "The system cannot find the file specified" (relating to "C:\HERE&T~1\"Jars\* in the classpath).
Can anyone suggest a way around this Microsoft mess?
[Edit]
As requested by Mofi below, here is a minimal reproducible example batch file:
#echo off
set base=%~d0%~sp0
echo %base%
If this is executed in a directory called "C:\Here & There", I would like the output to be
C:\HERE&T~1
without quotes or other extraneous output.
Here is the actual output when using CMD.EXE as the shell:
'T~1\' is not recognized as an internal or external command,
operable program or batch file.
C:\HERE
If I change the line #echo off to #echo on to show the commands as they are executed, I get this (where "C:\Here & There>" is the prompt, followed by the actual command being echoed prior to execution):
C:\Here & There> set base=C:\HERE & T~1\
'T~1\' is not recognized as an internal or external command,
operable program or batch file.
C:\Here & There> echo C:\HERE
C:\HERE
Since the quotes should not be part of the value, the correct SET command would be
set "base=%~d0%~sp0"
There are two problems, the first is the expansion in the SET command.
It can be avoided by quotes around the expression.
set "base=%~dps0"
The second problem is the echo, it can be avoided by quotes, too.
echo "%base%"
But then the quotes are visible, too.
In a batch file, this can be solved with delayed expansion:
set "base=%~dps0"
setlocal EnableDelayedExpansion
echo !base!
But on the command line, the delayed expansion mode can not be modified by setlocal, it can only be set by the /v:on option when cmd.exe starts
cmd /v:on
set "base=%~dps0"
echo !base!

Absolute path needed in batch file? [duplicate]

This question already has answers here:
What is the reason for "X is not recognized as an internal or external command, operable program or batch file"?
(4 answers)
What does %~dp0 mean, and how does it work?
(7 answers)
What is the reason for batch file path referenced with %~dp0 sometimes changes on changing directory?
(6 answers)
Closed 4 years ago.
I have a Windows batch file that calls the python interpreter:
python -m ...
That works. But now I have a second batch file that calls the first batch file. When I run this batch file, I get an error:
'python' is not recognized as an internal or external command,
operable program or batch file.
I don't understand why the second batch file doesn't work.
If it helps to have a concrete example, here's one:
In helloworld.py
print("Hello, world!")
In batch1.cmd
#echo off
echo About to call python...
python -m helloworld
pause
exit
In batch2.cmd
#echo off
set "path=%~dp0batch1.cmd"
start "" %path%
Output:
About to call python
'python' is not recognized as an internal or external command, operable program or batch file.
Press any key to continue . . .
You are completely breaking the system variable %path% by setting it in the batch. Now your system cannot find python anymore.
Simply change second batch to:
#echo off
set "mypath=%~dp0batch1.cmd"
start "" %mypath%
To explain the %path% variable better. It holds the path to any possible file locations to search for files to execute or open without the need to have the full path specified each time by a user. By running a command in cmd like python, it first checks the current directory where the batch started in, if python.exe is not there, it will search each semicolon seperated path in the %path% variable. When you set a new %path% variable it only knows of the newly set path and cannot find python to execute and you get the most common cmdline error on windows.
On another note, if you want to start batch1 in the same window, perhaps consider calling batch instead of starting it
call "%mypath%"

Ninja batch file as command

I want to use a batch file as a rule command in ninja like this
rule test
command = some-batch-file
but it results in
CreateProcess failed: The system cannot find the file specified.
It works when I prefix the command with cmd /c, but then I face the problem of the command-line length cap at 8191 or so characters. I found it hard finding information on why this doesn't work. My guess is that windows can really only execute .exe files with CreateProcess().
Can I make it work when it is passed directly to CreateProcess() or do I have to use cmd /c?

Error when i run a shortcut using it's path in cmd

I have a problem whenever I try to run some paths,
for example :
C:\Users\Dell\Desktop\Menu\program.lnk
I had this error:
not recognized as an internal or external command operable program or batch file.
As you can see this not a problem of space in the path, how can I solve this?
Having Tested This in the command prompt myself I found that on my windows 7 machine the command prompt doesn't like me appending the '.lnk' file extension on the end yet it seems to work to when I remove it. Other than I am not too sure. Could be a problem with the shortcut or the executable but I doubt it.
i just had to add cmd /C as prefix of the command

Ruby different results for "%x{something}" where "something" is quoted or unquoted

I'm using Ruby (2.0) %x{dir} under Windows 7 to run a DOS dir command. The dir being executed is different depending on whether or not dir is quoted.
When the command is bare I get the full output of a DOS dir command:
# sends output of cmd back to program
puts 'run %x{dir}'
puts "dir= " + %x{dir}
What I see on the command line:
run %x{dir}
dir= Volume in drive C is System
Volume Serial Number is FFFF-FFFF
Directory of C:\Users\ ...etc...
08/26/2013 09:16 AM <DIR> .
08/26/2013 09:16 AM <DIR> ..
01/28/2013 02:28 AM 10,958 AJAX RUG Test.tsc
...etc...
When I quote the dir command with either single or double quotes, I get back the output of GnuWin32 dir.exe command which is in the PATH. It took me a while to figure out that the GNU dir was being run. What is causing Ruby to use the dir built into CMD.EXE vs. c:\PROGRA~2\GnuWin32\bin\dir.EXE ???
Also, I've just noticed that my "Pickaxe" and "Ruby Cookbook" use the "%x{}" syntax (BRACES), where the online docs use "%x()" (PARENS) ... is this just a case of general delimiter matching by Ruby?
This is a peculiarity of Windows, not Ruby. What's going on is this:
Dir is not an executable but a native function of Windows/cmd.exe. (It's part of cmd.exe - so cmd.exe "traps" when you type dir and runs an internal function rather than looking for "dir.exe" or something out on your file path).
When you put something in quotes in cmd, it forces cmd.exe to look for that command on the path, not via it's internal functions.
You can test this by opening a command prompt in Windows and typing a built-in command (that doesn't exist in gnuwin32) such as copy:
>copy
The syntax of the command is incorrect.
>"copy"
'"copy"' is not recognized as an internal or external command,
operable program or batch file.
If you then create "copy.cmd" file with contents:
echo copy.cmd executed
when you run, you'll see:
>"copy"
copy.cmd executed
Make sense? Basically quoting the command you send to the shell (cmd.exe) from Ruby will cause a different interpretation by cmd.exe - it will prevent internal/built-in cmd.exe commands (such as dir and copy) from working, whereas external utils such as xcopy will work fine.

Resources