Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
690 views
in Technique[技术] by (71.8m points)

windows - How to conditionally take action if FINDSTR fails to find a string

I have a batch file as follows;

CD C:MyFolder
findstr /c:"stringToCheck" fileToCheck.bat
IF NOT XCOPY "C:OtherFolderfileToCheck.bat" "C:MyFolder" /s /y

I am getting an error ("C:OtherFolderfileToCheck.bat" was unexpected at this time.) when trying to execute this.

Please let me know what I am doing wrong.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...