5

I have a series of lines in a batch file (.bat) running on a Windows machine, e.g.:

start /b prog.exe cmdparam1 cmdparam2 > test1.txt
start /b prog.exe cmdparam1 cmdparam2 > test2.txt

Sometimes proj.exe returns nothing (empty) instead of useful data. In those cases I want to not generate a text file, is this something easily doable on the batch file side of things? The current behavior is that a text file is always created, in the case of empty output it's just a blank file.

user17753
  • 3,083
  • 9
  • 35
  • 73
  • 2
    Just [delete all files with zero length][1]. You can interleave those commands with the "start" commands. I.e. something like: [1]: http://stackoverflow.com/questions/4176962/recursively-delete-0kb-files-using-windows-cmd – jpe Aug 14 '12 at 19:48
  • @jpe -- that seems like the only possible answer if you want to handle it entirely in DOS. You should post it as an answer so it can be marked 'correct'. – James L. Aug 14 '12 at 19:52
  • Stack Overflow changed my answer into a comment because it was too short. So I elaborated a bit :) – jpe Aug 14 '12 at 19:57
  • To clarify, normally I would make changes to `prog.exe`, but I didn't write it and have no access to its source. So some DOS commands is all I have available atm. – user17753 Aug 14 '12 at 20:10

2 Answers2

4

The jpe solution requires your parent batch to know when the started processes have completed before it can check the output file sizes. You can use the START /WAIT option, but then you lose the advantage of running in parallel.

You can use the fact that redirection to a file will fail if another process has already redirected output to that same file. When your parent batch can redirect to them successfully then you know the started processes have all completed.

You probably should redirect stderr to your output file as well as stdout

@echo off

::start the processes and redirect the output to the ouptut files
start /b "" cmd /c prog.exe cmdparam1 cmdparam2 >test1.txt 2>&1
start /b "" cmd /c prog.exe cmdparam1 cmdparam2 >test2.txt 2>&1

::define the output files (must match the redirections above)
set files="test1.txt" "test2.txt"

:waitUntilFinished 
:: Verify that this parent script can redirect an unused file handle to the
:: output file (append mode). Loop back if the test fails for any output file.
:: Use ping to introduce a delay so that the CPU is not inundated.
>nul 2>nul ping -n 2 ::1
for %%F in (%files%) do (
  9>>%%F (
    rem
  )
) 2>nul || goto :waitUntilFinished

::Delete 0 length output files
for %%F in (%files%) do if %%~zF==0 del %%F
dbenham
  • 127,446
  • 28
  • 251
  • 390
  • `stdin` is `0`, `stdout` is `1`, `stderr` is `2`. Out of curiosity, what does the `9` part of `9>>%%F (` do? – James L. Aug 16 '12 at 17:38
  • It is the highest numbered unused file handle available to CMD.EXE. The file is created, and any output that is sent to that file handle will end up in the file, but of course nothing will ever go there under normal circumstances. It should work with any of the file handles 1-9, but I was just being cautious. – dbenham Aug 16 '12 at 18:04
2

Just delete all files with zero length. Edit: to accommodate the fact that start without the /WAIT flag returns before waiting the prog.exe to terminate, you could create the following wrapper script progwrapper.bat for your prog.exe:

prog.exe "%1" "%2" > "%3"
if %~z3==0 del "%3"

Then call the wrapper from your master script:

start /b progwrapper.bat cmdparam1 cmdparam2 > test1.txt
start /b progwrapper.bat cmdparam1 cmdparam2 > test2.txt

etc.

If prog.exe is a GUI app, then you should have a start /B /WAIT prog.exe in the progwrapper.bat.

Community
  • 1
  • 1
jpe
  • 1,013
  • 6
  • 14
  • 1
    This works, only issue is I'd have to put in a `/wait` flag on my `start`s because otherwise I'd try to delete before they were generated. – user17753 Aug 14 '12 at 20:07
  • @user17753 - Yes, your parent batch would have to know when to check the file size. I'm working on an answer that will allow multiple programs to run in parallel and not check the sizes until all are complete. – dbenham Aug 14 '12 at 20:18