Search code examples
batch-fileif-statementxcopyerrorlevel

How to write conditional statement that does something only if xcopy copies something (exit code 0)


I would like to create a conditional statement for xcopy that does something only if xcopy copies something.

So basically what I am saying is, if xcopy copies a file, do something.

If not do something else.

How this be done using a batch?

So far I have the following:

xcopy "Z:\TestFiles.zip" "C:\Test\" /d /y

if xcopy exit code 0 (

)else

UPDATE:

When running the following script:

xcopy /d /y "Z:\TestFiles.zip" "C:\Testing\"

echo %errorlevel%

The following are the results I get:

1 File(s) copied

C:\Users\jmills\Desktop>echo 0

0

_

0 File(s) copied

C:\Users\jmills\Desktop>echo 0

0

Because both error codes come out to 0 I cannot use:

IF ERRORLEVEL 1 GOTO FilesCopied
IF ERRORLEVEL 0 GOTO NoFiledCopied

:NoFiledCopied
REM do something
GOTO eof

:FilesCopied
REM  do something
GOTO eof

:eof

Solution

  • You could use the conditional execution operators && and ||:

    xcopy /D /Y "Z:\TestFiles.zip" "C:\Test\" && echo success. || echo Failure!
    

    Alternatively, you could check the ErrorLevel value:

    xcopy /D /Y "Z:\TestFiles.zip" "C:\Test\"
    rem // The following consition means 'if ErrorLevel is greater than or equal to 1':
    if ErrorLevel 1 (
        echo Failure!
    ) else (
        echo Success.
    )
    

    This works because xcopy does not return a negative ErrorLevel value.


    Or you could query the value of the %ErrorLevel% pseudo-variable:

    xcopy /D /Y "Z:\TestFiles.zip" "C:\Test\"
    if %ErrorLevel% equ 0 (
        echo Success.
    ) else (
        echo Failure!
    )
    

    Note that if the above code is placed within a (parenthesised) block of code, you need to enable and apply delayed variable expansion to get the latest !ErrorLevel! value.


    According to your update, you want to detect whether or not xcopy copied any files. As per this related Super User thread, xcopy never returns an exit code of 1 (which I consider a design flaw), contrary to the documentation, even if the /D option is used and no files are copied.

    To circumvent this you could capture the returned summary message (# File(s)) by a for /F loop, extract the number (#) and check whether it is greater than 0. The exit code should still be checked though as there might occur other exceptions:

    rem // Initialise variable:
    set "NUM=0"
    rem /* Use a `for /F` loop to capture the output of `xcopy` line by line;
    rem    the first token is stored in a variable, which is overwritten in
    rem    each loop iteration, so it finally holds the last token, which is
    ewm    nothing but the number of copied files; if `xcopy` fails, number `0`
    rem    is echoed, which is then captured as well: */
    for /F "tokens=1" %%E in ('
        2^> nul xcopy /D /Y "Z:\TestFiles.zip" "C:\Test\" ^|^| echo 0
    ') do (
        rem // Capture first token of a captured line:
        set "NUM=%%E"
    )
    rem // Compare the finally retrieved count of copied files:
    if %NUM% gtr 0 (
        echo Success.
    ) else (
        echo Failure!
    )
    

    Regard that the captured summary line is language-dependent, so the token to extract, as well as the echoed failure text (0), might need to be adapted accordingly.