Replacement for $() in Windows batch script - bash

I am trying to convert my bash script into a Windows batch file. It's a really simple one liner that's supposed to feed the contents of a file as arguments to script.exe, and send the results to output.txt.
This is the working bash script:
./script.exe $(cat input.txt) > output.txt
I know this might be bad style, but it works. The problem is, I have no idea how to do something like $() in a windows batch file. When I use it it sends the string "$(cat input.txt)" as the argument instead of running the command.

This bash construct is called command substitution. Here is a great answer from #MichaelBurr.
You can get a similar functionality using cmd.exe scripts with the
for /f command:
for /f "usebackq tokens=*" %%a in (`echo Test`) do my_command %%a
Yeah, it's kinda non-obvious (to say the least), but it's what's
there.
See for /? for the gory details.
Sidenote: I thought that to use "echo" inside the backticks in a
"for /f" command would need to be done using "cmd.exe /c echo
Test" since echo is an internal command to cmd.exe, but it works
in the more natural way. Windows batch scripts always surprise me
somehow (but not usually in a good way).
See also, on Superuser: Is there something like Command Substitution in WIndows CLI?

Related

Assigning a command BAT file environment variable via a perl script

I have a batch file I'm running under cmd.exe window. I want to look at a web config file and get a value. I have no idea of the right way to do this, but I figure I can cheat by writing a perl script to do this - and returning the value to the batch file.
I'm looking for something that looks like:
set var1=(evaluate perl script)
How does one do such a thing?
#echo off
set var1=
echo var1=%var1%
for /f "usebackq delims=" %%q in (`perl -E"say 'foo'"`) do set var1=%%q
echo var1=%var1%
Use %q instead of %%q outside of a batch file.

Trying to translate a linux shell script loop to Windows + GnuWin32

Edited to remove unnecessary usage of the "cat" command...
I have a Linux shell script that reads data out of a CSV file and performs operations based on the last column of each line in the file.
The input file has this basic format:
asdf,foo
1234,foo
qwerty,bar
zxcv,baz
7890,bar
The original Linux script looks like this:
sed s/.*,//g $1 | sort -u | while read item
do
# Do stuff with $item
done
I'm having a tough time translating the Linux script to run in a Windows shell environment with GnuWin32 versions of cat, sed, and sort. Here's what I've tried so far:
for /f "tokens=*" %%A in ('sed s/.*,//g %1 ^| sort -u') do (some stuff with %%A)
When I try to run this, I get:
sed: -e expression #1, char 4: unterminated `s' command
cat: write error: Invalid argument
I'm sure I'm misunderstanding something rudimentary about batch scripting. I tried to cover some basics like escape sequences, but I'm still drawing a blank. Any hints?
Thanks guys!
Try this:
for /f "delims=" %%A in ('cat "%~1" ^| sed "s/.*,//g" ^| sort -u') do (some stuff with %%A)
In Windows replace the single quotes from linux shell script ' with double quotes ". If you need double quotes in GNUWin commands, it must be escaped by a backslash \ - but only on the Windows shell prompt cmd, the scripts from sed, awk etc. are fully compatible.

cmd script printing out but not executing

Hi all I'm currently writing up a small bash script to automate some stuff for me but I've hit a bit of a snag My current file looks like the following:
for /f "delims=" %%f in ('dir /b "D:/*"') do C:\MediaInfo\MediaInfo.exe "--Inform=Video;%Width% "D:\%%f"
pause > nul
The pause thing is just there so I can see the output. While the part after the |do| command works fine if I manually type it in (as in I know my syntax for that is correct) however when running the batch script instead of actually executing the above commands it simply prints them out to the command console. Am I missing some syntax here or similar. Also as a side note I would like to push the resulting value of that query into an int so I can use it, do you know if this is possible in bash or should I look at trying to use a higher level language? Thanks!
I have no notion of the intricacies of mediainfo - but it would be unusual if it was to accept unbalanced quotes in its command line as you have posted. I'd suggest an extra after %Width%

Use shebang/hashbang in Windows Command Prompt

I'm currently using the serve script to serve up directories with Node.js on Windows 7. It works well in the MSYS shell or using sh, as I've put node.exe and the serve script in my ~/bin (which is on my PATH), and typing just "serve" works because of it's Shebang (#!) directive which tells the shell to run it with node.
However, Windows Command Prompt doesn't seem to support normal files without a *.bat or *.exe extension, nor the shebang directive. Are there any registry keys or other hacks that I can get to force this behavior out of the built-in cmd.exe?
I know I could just write up a simple batch file to run it with node, but I was wondering if it could be done in a built-in fasion so I don't have to write a script for every script like this?
Update: Actually, I was thinking, is it possible to write a default handler for all 'files not found' etc. that I could automatically try executing within sh -c?
Thanks.
Yes, this is possible using the PATHEXT environment variable. Which is e.g. also used to register .vbs or .wsh scripts to be run "directly".
First you need to extend the PATHEXT variable to contain the extension of that serve script (in the following I assume that extension is .foo as I don't know Node.js)
The default values are something like this:
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
You need to change it (through the Control Panel) to look like this:
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.FOO
Using the control panel (Control Panel -> System -> Advanced System Settings -> Environment Variables is necessary to persist the value of the PATHEXT variable.
Then you need to register the correct "interpreter" with that extension using the commands FTYPE and ASSOC:
ASSOC .foo=FooScript
FTYPE FooScript=foorunner.exe %1 %*
(The above example is shamelessly taken from the help provided by ftype /?.)
ASSOC and FTYPE will write directly into the registry, so you will need an administrative account to run them.
Command prompt does not support shebang , however there are a lot hybrid techniques for different languages that you allow to combine batch and other languages syntax in one file.As your question concerns node.js here's a batch-node.js hybrid (save it with .bat or .cmd extension):
0</* :{
#echo off
node %~f0 %*
exit /b %errorlevel%
:} */0;
console.log(" ---Self called node.js script--- ");
console.log('Press any key to exit');
process.stdin.setRawMode(true);
process.stdin.resume();
process.stdin.on('data', process.exit.bind(process, 0));
It is possible to be done with many other languages like Ruby,Perl,Python,PHP and etc.
Here is a simple way to force windows to support shebang however it has a caveat regarding the file naming. Copy the following text in to a batch file and follow general idea in REM comments.
#echo off
REM This batch file adds a cheesy shebang support for windows
REM Caveat is that you must use a specific extension for your script files and associate that extension in Windows with this batch program.
REM Suggested extension is .wss (Windows Shebang Script)
REM One method to still easily determine script type visually is to use double extensions. e.g. script.pl.wss
setlocal enableextensions disabledelayedexpansion
if [%1] == [] goto usage
for /f "usebackq delims=" %%a IN (%1) do (
set shebang=%%a
goto decode_shebang
)
:decode_shebang
set parser=%shebang:~2%
if NOT "#!%parser%" == "%shebang%" goto not_shebang
:execute_script
"%parser%" %*
set exit_stat=%errorlevel%
echo script return status: %exit_stat%
goto finale
:not_shebang
echo ERROR script first line %shebang% is not a valid shebang
echo maybe %1 is not a shebanged script
goto finale
:usage
echo usage: %0 'script with #! shebang' [scripts args]+
echo This batch file will inspect the shebang and extract the
echo script parser/interpreter which it will call to run the script
:finale
pause
exit /B %exit_stat%
No, there's no way to "force" the command prompt to do this.
Windows simply wasn't designed like Unix/Linux.
Is there a shell extension that does something similar?
Not that I've heard of, but that should be asked on Super User, not here.
There's no way to execute random file, unless it is an actual executable binary file. Windows CreateProcess() function just not designed for it. The only files it can execute are those with MZ magic or with extensions from %PATHEXT% list.
However, CMD itself has a limited support for custom interpreters through EXTPROC clause. The limitation is that interpreter should also support and omit this clause in its execution.
#npocmaka Thanks for the hint! After some trial and error I found the equivalent for a batch/php hybrid is as follows:
<?/** :
#echo off
C:\tools\php81\php.exe -d short_open_tag=On %~f0 %*
exit /b
*/ ?>
<?php
header('Location: example.com/');
print("<body><h1>Hello PHP!<h1></body>");
?>

Batch equivalent of Bash backticks

When working with Bash, I can put the output of one command into another command like so:
my_command `echo Test`
would be the same thing as
my_command Test
(Obviously, this is just a non-practical example.)
I'm just wondering if you can do the same thing in Batch.
You can get a similar functionality using cmd.exe scripts with the for /f command:
for /f "usebackq tokens=*" %%a in (`echo Test`) do my_command %%a
Yeah, it's kinda non-obvious (to say the least), but it's what's there.
See for /? for the gory details.
Sidenote: I thought that to use "echo" inside the backticks in a "for /f" command would need to be done using "cmd.exe /c echo Test" since echo is an internal command to cmd.exe, but it works in the more natural way. Windows batch scripts always surprise me somehow (but not usually in a good way).
You can do it by redirecting the output to a file first. For example:
echo zz > bla.txt
set /p VV=<bla.txt
echo %VV%
Read the documentation for the "for" command: for /?
Sadly I'm not logged in to Windows to check it myself, but I think something like this can approximate what you want:
for /F %i in ('echo Test') do my_command %i
Maybe I'm screwing up the syntax of the standard for /f method, but when I put a very complex command involving && and | within the backticks in the limit of the for /f, it causes problems. A slight modification from the usual is possible to handle an arbitrary complexity command:
SET VV=some_command -many -arguments && another_command -requiring -the-other -command | handling_of_output | more_handling
for /f "usebackq tokens=*" %%a in (`%VV%`) do mycommand %%a
By putting your full and complex command in a variable first, then putting a reference to the variable in the limit rather than putting the complex command directly into the limit of the for loop, you can avoid syntax interpretation issues. Currently if I copy the exact command I have set to the VV variable in the example above into where it's used, %VV%, it causes syntax errors.
You could always run Bash inside Windows. I do it all the time with MSYS (much more efficient than Cygwin).

Resources