I have a batch file as follows;
CD C:\MyFolder findstr /c:"stringToCheck" fileToCheck.bat IF NOT XCOPY "C:\OtherFolder\fileToCheck.bat" "C:\MyFolder" /s /y
I am getting an error ("C:\OtherFolder\fileToCheck.bat" was unexpected at this time.) when trying to execute this.
Please let me know what I am doing wrong.
FINDSTR will set %ERRORLEVEL% as follows: 0 (False) a match is found in at least one line of at least one file. 1 (True) if a match is not found in any line of any file, (or if the file is not found at all). 2 Wrong syntax An invalid switch will only print an error message in error stream.
The find program supports UTF-16, which findstr doesn't; on the other hand, the findstr program supports regular expressions, which find does not. The reason why their feature sets are unrelated is that the two programs are unrelated. The find program came first.
Search for a text string in a file (or multiple files) unlike the simple FIND command FINDSTR supports more complex regular expressions.
The findstr (short for find string) command is used in MS-DOS to locate files containing a specific string of plain text.
I presume you want to copy C:\OtherFolder\fileToCheck.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:\MyFolder\fileToCheck.bat" >nul 2>&1 if errorlevel 1 xcopy "C:\OtherFolder\fileToCheck.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:\MyFolder\fileToCheck.bat" >nul 2>&1 if not %errorlevel% == 0 xcopy "C:\OtherFolder\fileToCheck.bat" "c:\MyFolder"
or
findstr /c:"stringToCheck" "c:\MyFolder\fileToCheck.bat" >nul 2>&1 if %errorlevel% neq 0 xcopy "C:\OtherFolder\fileToCheck.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:\MyFolder\fileToCheck.bat" >nul 2>&1 || xcopy "C:\OtherFolder\fileToCheck.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.
You are not evaluating a condition for the IF. I am guessing you want to not copy if you find stringToCheck in fileToCheck. You need to do something like (code untested but you get the idea):
CD C:\MyFolder findstr /c:"stringToCheck" fileToCheck.bat IF NOT ERRORLEVEL 0 XCOPY "C:\OtherFolder\fileToCheck.bat" "C:\MyFolder" /s /y
EDIT by dbenham
The above test is WRONG, it always evaluates to FALSE.
The correct test is IF ERRORLEVEL 1 XCOPY ...
Update: I can't test the code, but I am not sure what return value findstr actually returns if it doesn't find anything. You might have to do something like:
CD C:\MyFolder findstr /c:"stringToCheck" fileToCheck.bat > tempfindoutput.txt set /p FINDOUTPUT= < tempfindoutput.txt IF "%FINDOUTPUT%"=="" XCOPY "C:\OtherFolder\fileToCheck.bat" "C:\MyFolder" /s /y del tempfindoutput.txt
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With