Reputation: 3178
If we have a batch file being redirected to a log like so:
C:\Testing\Example.bat > C:\Testing\Example.log
Is there any way inside the batch file to determine if there's a standard output redirect happening to a log file?
Basically the batch file I have requires three arguments passed to it. When arguments are left out, the batch file prints a usage example much like regular Windows commands would, and throws a 'pause' out so instructions can be read. However if the batch is called without arguments AND it's being logged, then the batch file will just sit there forever waiting for a key to break the pause, but won't show anything on the screen.
Normally this wouldn't be a problem at all, however I'm trying to make this idiot-proof since I won't be the one implementing the batch file in other scripts/scheduled tasks.
At this point it seems like I need to get rid of the usage pause entirely, but I was hoping for a solution where I wouldn't have to. Thanks for the help.
Upvotes: 4
Views: 1917
Reputation: 82267
You could check if stdout
is redirected with a small trick.
It uses the fact that outputting backspaces after a TAB moves the cursor back and if the cursor shall be moved before the home position in this situation, an error will be created to get a hint in your logfiles for the strange characters.
The drawback is, that it outputs <FF><TAB>><BACKSPACE><BACKSPACE><CR><LF>
to stdout.
When stdout is the console, it simply clears it.
But when stdout is redirected to a file you append these characters to the file, but it can be commented with a meaningful text.
@echo off
setlocal
call :createTAB_BS
echo Script started, test for redirection:
cls
( echo %%TAB%%%%BS%%%%BS%%) | ( findstr "^" 2^> nul)
if %errorlevel% EQU 0 (
>CON echo stdout is redirected
) ELSE (
echo stdout goes to the console
)
exit /b
:createTAB_BS
for /f "tokens=1,2 delims=," %%A in ('forfiles /p "%~dp0." /m "%~nx0" /c "cmd /c echo(0x09,0x08"') do (
set "TAB=%%A"
set "BS=%%B"
)
exit /b
Upvotes: 1
Reputation: 130819
There is no good way to determine if stdin or stdout has been redirected using native batch commands.
But there is no need to worry about redirection in your case. Simply redirect the PAUSE stdin and stdout to con, and you don't have to worry about prior redirection.
pause <con >con
It is possible to cleanly detect whether stdin and/or stdout and/or stderr has likely been redirected. But I haven't figured out a way to non-destructively determine which of those handles was redirected.
@echo off
2>nul (5>&4 break) && (
>con echo There has been redirection
) || (
>con echo No redirection found
)
The technique relies on the fact that whenever an existing handle is redirected, the old definition is saved in the lowest available undefined handle.
If there has not been any redirection, then 2>nul
saves stderr in 3, and 4 is undefined. So 5>&4
fails, and the ||
branch is fired.
If there has been redirection, then 3 has already been defined to preserve the original value of the redirected handle, so 2>nul
will save stderr in 4 (unless 4 has also already been used by some other redirection). Either way, the 5>&4
will succeed because 4 is defined, so the &&
branch will fire.
If the test reports that there has been redirection, then at least one of the following must be true:
Unfortunately, I cannot determine which of the above are true, except for...
Over at DosTips, SiberiaMan has published a simple technique to determine if stdin has been redirected or is receiving a pipe:
2>nul >nul timeout /t 0 && (
>con echo stdin not redirected or piped
) || (
>con echo stdin has been redirected or is receiving piped input
)
Upvotes: 4
Reputation: 206
I think you just ask the wrong question. you want to find a way to end the batch with extra break when in cmd mode. and stop in batch mode without pausing. You can use CMDpause this will make a variable named cmdpause examples https://www.administrator.de/wissen/batchcode-erstellen-fehler-batch-leichter-finden-184736.html https://www.dostips.com/forum/viewtopic.php?t=7257#p47510
there is something from Dave and jeb. But I have no link.
Phil
Upvotes: 1
Reputation: 125
There isn't a way in standard Windows batch files (that I'm aware of) to determine where STDOUT is being redirected, or even if it is being redirected. However, you might wish to write your usage examples out to STDERR instead of STDOUT, so at least a simple redirect into a file will not capture the usage info.
Example test.cmd:
@ECHO OFF
ECHO Test output 1>&2
PAUSE 1>&2
Then call it:
test.cmd > output.log
Which will still output:
Test output
Press any key to continue . . .
Of course, this does nothing for when the file is called with STDERR being redirected.
test.cmd 2> error.log
Upvotes: 0
Reputation: 6657
I am not aware of any way to do this using only batch and standard commands. However, there are tricks that can be used from other languages such as native C or C# programs, if it's important enough to you to include another .exe along with your .bat.
Here is a sneaky approach. This batch file creates a .com file, then calls it to test the stdout handle: http://www.dostips.com/forum/viewtopic.php?f=3&t=2800
This explains how to do it with C#, if you want to write a simple C# helper programme: Check if output is redirected. That makes me think it should also be possible from Powershell, but I haven't tried.
Upvotes: 2