I presume you want to copy C:OtherFolderfileToCheck.bat to C:MyFolder if the existing file in C:MyFolder is either missing entirely, or if it is missing "stringToCheck".
FINDSTR sets ERRORLEVEL to 0 if the string is found, to 1 if it is not. It also sets errorlevel to 1 if the file is missing. It also prints out each line that matches. Since you are trying to use it as a condition, I presume you don't need or want to see any of the output. The 1st thing I would suggest is to redirect both the normal and error output to nul using >nul 2>&1
.
Solution 1 (mostly the same as previous answers)
You can use IF ERRORRLEVEL N
to check if the errorlevel is >= N. Or you can use IF NOT ERRORLEVEL N
to check if errorlevel is < N. In your case you want the former.
findstr /c:"stringToCheck" "c:MyFolderfileToCheck.bat" >nul 2>&1
if errorlevel 1 xcopy "C:OtherFolderfileToCheck.bat" "c:MyFolder"
Solution 2
You can test for a specific value of errorlevel by using %ERRORLEVEL%. You can probably check if the value is equal to 1, but it might be safer to check if the value is not equal to 0, since it is only set to 0 if the file exists and it contains the string.
findstr /c:"stringToCheck" "c:MyFolderfileToCheck.bat" >nul 2>&1
if not %errorlevel% == 0 xcopy "C:OtherFolderfileToCheck.bat" "c:MyFolder"
or
findstr /c:"stringToCheck" "c:MyFolderfileToCheck.bat" >nul 2>&1
if %errorlevel% neq 0 xcopy "C:OtherFolderfileToCheck.bat" "c:MyFolder"
Solution 3
There is a very compact syntax to conditionally execute a command based on the success or failure of the previous command: cmd1 && cmd2 || cmd3
which means execute cmd2 if cmd1 was successful (errorlevel=0), else execute cmd3 if cmd1 failed (errorlevel<>0). You can use && alone, or || alone. All the commands need to be on the same line. If you need to conditionally execute multiple commands you can use multiple lines by adding parentheses
cmd1 && (
cmd2
cmd3
) || (
cmd4
cmd5
)
So for your case, all you need is
findstr /c:"stringToCheck" "c:MyFolderfileToCheck.bat" >nul 2>&1 || xcopy "C:OtherFolderfileToCheck.bat" "c:MyFolder"
But beware - the ||
will respond to the return code of the last command executed. In my earlier pseudo code the ||
will obviously fire if cmd1 fails, but it will also fire if cmd1 succeeds but then cmd3 fails.
So if your success block ends with a command that may fail, then you should append a harmless command that is guaranteed to succeed. I like to use (CALL )
, which is harmless, and always succeeds. It also is handy that it sets the ERRORLEVEL to 0. There is a corollary (CALL)
that always fails and sets ERRORLEVEL to 1.