windows 如果 FINDSTR 找不到字符串,如何有条件地采取行动

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8530976/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 09:01:24  来源:igfitidea点击:

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

windowsbatch-filecmd

提问by testndtv

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.

尝试执行此操作时出现错误(此时“C:\OtherFolder\fileToCheck.bat”是意外的。)。

Please let me know what I am doing wrong.

请让我知道我做错了什么。

采纳答案by Luke Kim

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):

您不是在评估 IF 的条件。如果您在 fileToCheck 中找到 stringToCheck,我猜您不想复制。你需要做一些类似的事情(代码未经测试,但你明白了):

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 ...

dbenham 编辑
上面的测试是错误的,它总是评估为 FALSE。
正确的测试是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:

更新:我无法测试代码,但我不确定如果 findstr 没有找到任何东西,它实际返回的返回值是什么。您可能必须执行以下操作:

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

回答by dbenham

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".

如果 C:\MyFolder 中的现有文件完全丢失,或者缺少“stringToCheck”,我认为您想将 C:\OtherFolder\fileToCheck.bat 复制到 C:\MyFolder。

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.

如果找到字符串,FINDSTR 将 ERRORLEVEL 设置为 0,否则设置为 1。如果文件丢失,它还会将错误级别设置为 1。它还打印出匹配的每一行。由于您试图将其用作条件,因此我认为您不需要或不想看到任何输出。我建议的第一件事是使用>nul 2>&1.

Solution 1(mostly the same as previous answers)

解决方案 1(与之前的答案大致相同)

You can use IF ERRORRLEVEL Nto check if the errorlevel is >= N. Or you can use IF NOT ERRORLEVEL Nto check if errorlevel is < N. In your case you want the former.

您可以使用IF ERRORRLEVEL N检查错误级别是否 >= N。或者您可以使用IF NOT ERRORLEVEL N检查错误级别是否 < N。在您的情况下,您需要前者。

findstr /c:"stringToCheck" "c:\MyFolder\fileToCheck.bat" >nul 2>&1
if errorlevel 1 xcopy "C:\OtherFolder\fileToCheck.bat" "c:\MyFolder"

Solution 2

解决方案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.

您可以使用 %ERRORLEVEL% 测试错误级别的特定值。您可能可以检查该值是否等于 1,但检查该值是否不等于 0 可能更安全,因为只有在文件存在且包含字符串时才将其设置为 0。

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

解决方案3

There is a very compact syntax to conditionally execute a command based on the success or failure of the previous command: cmd1 && cmd2 || cmd3which 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这意味着如果 cmd1 成功(errorlevel=0)则执行 cmd2,否则如果 cmd1 失败(errorlevel<>0)则执行 cmd3。您可以单独使用 && 或 || 独自的。所有命令都需要在同一行上。如果需要有条件地执行多个命令,可以通过添加括号来使用多行

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.

但要注意 -||将响应最后执行的命令的返回码。在我之前的伪代码中,||如果 cmd1 失败,它显然会触发,但如果 cmd1 成功但 cmd3 失败,它也会触发。

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.

因此,如果您的成功块以可能失败的命令结束,那么您应该附加一个保证成功的无害命令。我喜欢使用(CALL ),这是无害的,并且总是成功。将 ERRORLEVEL 设置为 0 也很方便。 有一个推论(CALL)总是失败并将 ERRORLEVEL 设置为 1。

回答by Aacini

In DOS/Windows Batch most commands return an exitCode, called "errorlevel", that is a value that customarily is equal to zero if the command ends correctly, or a number greater than zero if ends because an error, with greater numbers for greater errors (hence the name).

在 DOS/Windows Batch 中,大多数命令返回一个 exitCode,称为“errorlevel”,如果命令正确结束,该值通常等于 0,如果由于错误而结束,则该值通常等于 0,如果由于错误而结束,则数字越大,错误越大(由此得名)。

There are a couple methods to check that value, but the original one is:

有几种方法可以检查该值,但原始方法是:

IF ERRORLEVEL value command

Previous IF test if the errorlevel returned by the previous command was GREATER THAN OR EQUAL the given value and, if this is true, execute the command. For example:

上一个 IF 测试上一个命令返回的错误级别是否大于或等于给定值,如果为真,则执行该命令。例如:

verify bad-param
if errorlevel 1 echo Errorlevel is greater than or equal 1
echo The value of errorlevel is: %ERRORLEVEL%

Findstr command return 0 if the string was found and 1 if not:

如果找到字符串,则 Findstr 命令返回 0,否则返回 1:

CD C:\MyFolder
findstr /c:"stringToCheck" fileToCheck.bat
IF ERRORLEVEL 1 XCOPY "C:\OtherFolder\fileToCheck.bat" "C:\MyFolder" /s /y

Previous code will copy the file if the string was NOT found in the file.

如果在文件中未找到该字符串,则先前的代码将复制该文件。

CD C:\MyFolder
findstr /c:"stringToCheck" fileToCheck.bat
IF NOT ERRORLEVEL 1 XCOPY "C:\OtherFolder\fileToCheck.bat" "C:\MyFolder" /s /y

Previous code copy the file if the string was found. Try this:

如果找到字符串,则先前的代码复制文件。尝试这个:

findstr "string" file
if errorlevel 1 (
    echo String NOT found...
) else (
    echo String found
)

回答by Justin Goldberg

I tried to get this working using FINDSTR, but for some reason my "debugging" command always output an error level of 0:

我尝试使用 FINDSTR 使其正常工作,但由于某种原因,我的“调试”命令始终输出错误级别 0:

ECHO %ERRORLEVEL%

My workaround is to use Grep from Cygwin, which outputs the right errorlevel (it will give an errorlevel greater than 0) if a string is not found:

我的解决方法是使用 Cygwin 中的 Grep,如果找不到字符串,它会输出正确的错误级别(它将给出大于 0 的错误级别):

dir c:\*.tib >out 2>>&1
grep "1 File(s)" out
IF %ERRORLEVEL% NEQ 0 "Run other commands" ELSE "Run Errorlevel 0 commands"

Cygwin's grep will also output errorlevel 2 if the file is not found. Here's the hash from my version:

如果找不到文件,Cygwin 的 grep 也会输出错误级别 2。这是我的版本的哈希值:

C:\temp\temp>grep --version grep (GNU grep) 2.4.2

C:\temp\temp>grep --version grep (GNU grep) 2.4.2

C:\cygwin64\bin>md5sum grep.exe c0a50e9c731955628ab66235d10cea23 *grep.exe

C:\cygwin64\bin>md5sum grep.exe c0a50e9c731955628ab66235d10cea23 *grep.exe

C:\cygwin64\bin>sha1sum grep.exe ff43a335bbec71cfe99ce8d5cb4e7c1ecdb3db5c *grep.exe

C:\cygwin64\bin>sha1sum grep.exe ff43a335bbec71cfe99ce8d5cb4e7c1ecdb3db5c *grep.exe