Standard output and error output from robocopy in a batch file

15,757

Solution 1

The solution to your problem with having both a standard log and an error log is to create a TEMPORARY log, then decide what to do with it.

I have also found some problems with ROBOCOPY and the reporting of errors.

1) If you create a log file using the built-in /log:file or /log+:file, not all errors end up in the log.
2) Additionally not all errors get reported to ERRORLEVEL.
3) Lastly, successful copy may be reported as an ERRORLEVEL 1.

To combat this, I use 3 methods to capture all the errors. First I redirect STDOUT to a temporary log file, then I check two places in that log file for the word "ERROR", third also check ERRORLEVEL.

Part of the problem is that ROBOCOPY put's two EOF characters at the end of it's log files. Normally that's not a problem, except when attempting to concatenate files like I am here. When you normally concatenate a file the last character (the EOF character) is overwritten. But if there are TWO EOF characters, everything appended to the file goes after that, so when you access the file in normal ways you do not see any of the appended data.

setlocal

set Source=<somedir>
set Dest=<someotherdir>
set Files=*.* or afile anotherfile yetathridfile
set Options=

set STDLog=STANDART.LOG
set ErrLog=ERROR.LOG
set TMPLog=TMP.LOG
set err=

:: If nessicary make 0 byte log files
if not exist %ErrLog% copy nul %ErrLog%
if not exist %STDLog% copy nul %STDLog%

:: Create a header in the temporary log file to make each entry more visable
echo.>%TMPLog%
echo ===============================================================================>> %TMPLog%
echo ===============================================================================>> %TMPLog%
echo.>> %TMPLog%
echo Started : %date:~-4%/%date:~4,5% %time%>> %TMPLog%

:: Record how ROBOCOPY was called
echo ROBOCOPY %source% %dest% %files% %options%>>%TMPLog%

:: Call ROBOCOPY and redirect STDOUT to %TMPLog%
ROBOCOPY %source% %dest% %files% %options%>>%TMPLog%

:: Depending on the error, it may be in the first or third token.
:: So we need to check both.
for /f "tokens=1,3" %%x in (%TMPLog%) do (
  if "%%x"=="ERROR" SET err=TRUE
  if "%%y"=="ERROR" SET err=TRUE
)

:: The error also MAY be reported via ERRORLEVEL
:: 0 = No error, all files skipped (because they are the same in both dirs)
:: 1 = No error, some or all files copied.
:: 2 = Destination DIR contains extra files the source does not.
set error=%errorlevel%
if %errorlevel% gtr 2 set err=TRUE

if "%err%"=="TRUE" (
  REM However we got the error, copy the temp log to the error log.
  REM Copy both files as ASCII. Otherwise you'll have trouble. (This caused me BIG headaches.)
  REM The command states that the two source files are ASCII and the destination is ASCII
  copy /a %ErrLog% + /a %TMPLog%=/a %ErrLog%
) else (
  REM If no errors, copy the temp log to the standard log.
  REM Copy both files as ASCII. Otherwise you'll have trouble. (This caused me BIG headaches.)
  copy /a %STDLog% + /a %TMPLog%=/a %STDLog%
)

:: Delete the temporary log file
del %TMPLog%

:: set the errorlevel to ROBOCOPY's errorlevel and reset all variables
endlocal & exit /b %error%

Solution 2

Based on a few tests it seems that ROBOCOPY does not use stderr. It appears error messages are sent to stdout along with all other output. So I don't think you can do what you want.

I tested by intentionally issuing ROBOCOPY with errors and redirecting stderr to nul. The errors still appear on the screen.

ROBOCOPY Let's generate an error :) 2>nul
Share:
15,757
zipi
Author by

zipi

Updated on August 21, 2022

Comments

  • zipi
    zipi over 1 year

    I use robocopy in my batch file to copy folders. I want standard output to go to one log file and error messages to go to another log file.

    I tried the following:

    robocopy Z\BR  "C\WIN"  /E /LOG+:STANDART.LOG  2 /LOG+:ERROR.LOG 
    

    but "if there are no errors" (not sure what the OP meant) and the standard output is going to the ERROR.LOG. Can anyone help me?

  • zipi
    zipi over 11 years
    but when I try it ERROR.LOG is empty and the error apear in STANDART.LOG
  • James K
    James K over 11 years
    Odd. Is all output ending up in STANDART.LOG? It may be that if you really want two logs that you'll have to parse the output yourself and "direct traffick" to the proper files.
  • James K
    James K over 11 years
    @zipi - I believe that this is a complete answer for you. The solution is to make a temporary log, THEN decide what to do with it.
  • James K
    James K over 11 years
    It would be nice if Microsoft documented ROBOCOPY's use of the ERRORLEVEL, and if ROBOCOPY dealt with errors in a consistent fashon.
  • zipi
    zipi over 11 years
    :: 2 = Destination DIR contains extra files the source does not I dont understand why the error level 2 is error??I want to copy files to destination folder,and if there was a change in one of the file replace it,but it possible that there is a file in destination folder that dont exit in the source folder?!
  • James K
    James K over 11 years
    @zipi - Neither ERRORCODE 1 or 2 is an error. It's just a non-standard way to use the exit code ( what Microsoft calls the ERRORLEVEL ). That's just what Bill (or whomever) called it when MSDOS was created way back when, and they've stuck with the term. It would actually be better (less confusing) to name it EXITCODE, but ERRORLEVEL has stuck and will be stuck at least until Windows bites it.
  • James K
    James K over 11 years
    @zipi - That (my above comment) is why I ignore values less then 3 when I check the ERRORLEVEL: if %errorlevel% gtr 2 set err=TRUE
  • zipi
    zipi over 11 years
    this errorLevel shuld be contain 1 ,2 or 3?or many option?you mean that I need to fit my validation Respectively to my requirement in specify copy?
  • James K
    James K over 11 years
    @zipi - Normally, 0 is no error, and any other value is an error, different values being different types of errors. So usually you only need to see if the ERRORLEVEL is 0 or not to know if there was an error. In this case, ERRORLEVELs 0, 1, and 2 all mean different types of no errors.
  • James K
    James K over 11 years
    @zipi - ERRORLEVEL can contain any number. If you type nonsense at the command prompt, then type echo %errorlevel% the system will print 9009 that ERRORLEVEL basically means Command, Program, or Script Not Found.
  • zipi
    zipi over 11 years
    in this case..all mean different types of no errors.. you mean your example code or general in robcopy mechanizer?
  • James K
    James K over 11 years
    @zipi - I mean in ROBOCOPY. Though my code does pass that value back to the user / calling program.
  • James K
    James K over 11 years
    @zipi - If you could upvote and select my answer then? Plz? :)
  • zipi
    zipi over 11 years
    Hi,I select your answer but I can not do upvote because I have no minimum of 15 points..
  • zipi
    zipi over 11 years
    Hi,you wrote in your code: if "%%y"=="ERROR" SET err=TRUE,what the y??x its part of the for but y?
  • James K
    James K over 11 years
    @zipi - Yes, I first indicate that there will be two tokens: "tokens=1,3" in position 1 and position three. Since I specified %%x as token 1, %%y becomes token 2.