Как условно выполнить действие, если FINDSTR не может найти строку - PullRequest
23 голосов
/ 16 декабря 2011

У меня есть пакетный файл следующим образом:

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

Я получаю ошибку ("C: \ OtherFolder \ fileToCheck.bat" в это время был неожиданным.) При попытке выполнить это.1004 *

Пожалуйста, дайте мне знать, что я делаю неправильно.

Ответы [ 4 ]

65 голосов
/ 16 декабря 2011

Я предполагаю, что вы хотите скопировать C: \ OtherFolder \ fileToCheck.bat в C: \ MyFolder, если существующий файл в C: \ MyFolder либо полностью отсутствует, либо если отсутствует "stringToCheck".

FINDSTR устанавливает ERRORLEVEL в 0, если строка найдена, в 1, если это не так. Он также устанавливает errorlevel на 1, если файл отсутствует. Он также распечатывает каждую строку, которая соответствует. Поскольку вы пытаетесь использовать его как условие, я полагаю, что вам не нужно или вы не хотите видеть какие-либо результаты. Первое, что я хотел бы предложить, это перенаправить как нормальный, так и вывод ошибок на nul, используя >nul 2>&1.

Решение 1 (в основном то же, что и предыдущие ответы)

Вы можете использовать IF ERRORRLEVEL N, чтобы проверить, равен ли уровень ошибок> = N. Или вы можете использовать IF NOT ERRORLEVEL N, чтобы проверить, равен ли уровень ошибок

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

Решение 2

Вы можете проверить определенное значение уровня ошибки, используя% 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"

или

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

Решение 3

Существует очень компактный синтаксис для условного выполнения команды на основе успеха или неудачи предыдущей команды: cmd1 && cmd2 || cmd3, что означает выполнение cmd2, если cmd1 был успешным (errorlevel = 0), иначе выполнение cmd3, если cmd1 не удалось (errorlevel) <> 0). Вы можете использовать && отдельно или || в одиночестве. Все команды должны быть в одной строке. Если вам нужно условно выполнить несколько команд, вы можете использовать несколько строк, добавив скобки

cmd1 && (
   cmd2
   cmd3
) || (
   cmd4
   cmd5
)

Так что для вашего случая все, что вам нужно, это

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

Но будьте осторожны - || ответит на код возврата последней выполненной команды. В моем предыдущем псевдокоде ||, очевидно, будет срабатывать при сбое cmd1, но также будет срабатывать при успешном выполнении cmd1, но затем при сбое cmd3.

Так что, если ваш успешный блок заканчивается командой, которая может потерпеть неудачу, тогда вы должны добавить безвредную команду, которая гарантированно будет успешной. Мне нравится использовать (CALL ), который безвреден и всегда успешен. Также удобно, что он устанавливает ERRORLEVEL в 0. Существует следствие (CALL), которое всегда терпит неудачу и устанавливает ERRORLEVEL в 1.

9 голосов
/ 16 декабря 2011

Вы не оцениваете условие для IF. Я предполагаю, что вы не хотите копировать, если вы найдете stringToCheck в fileToCheck. Вам нужно сделать что-то вроде (код не проверен, но вы поняли идею):

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

РЕДАКТИРОВАТЬ по dbenham
Вышеприведенный тест НЕПРАВИЛЬНЫЙ, он всегда оценивается как ЛОЖЬ.
Правильный тест IF ERRORLEVEL 1 XCOPY ...

Обновление: я не могу проверить код, но я не уверен, какое возвращаемое значение на самом деле возвращает 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
5 голосов
/ 16 декабря 2011

В DOS / Windows Batch большинство команд возвращают код выхода, называемый «errorlevel», то есть значение, которое обычно равно нулю, если команда заканчивается правильно, или числу больше нуля, если оно заканчивается из-за ошибки, с большими числами для больших ошибок (отсюда и название).

Есть несколько способов проверить это значение, но оригинал:

IF ERRORLEVEL value command

Предыдущий тест IF, если уровень ошибки, возвращенный предыдущей командой, был БОЛЬШЕ, ЧЕМ ИЛИ РАВНЫМ заданным значением, и, если это так, выполнить команду. Например:

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

Команда Findstr возвращает 0, если строка была найдена, и 1, если нет:

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

Предыдущий код будет копировать файл, если строка НЕ ​​была найдена в файле.

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

Предыдущий код скопировать файл, если строка была найдена. Попробуйте это:

findstr "string" file
if errorlevel 1 (
    echo String NOT found...
) else (
    echo String found
)
0 голосов
/ 09 февраля 2015

Я пытался заставить это работать, используя FINDSTR, но по какой-то причине моя команда «отладки» всегда выводила уровень ошибки 0:

ECHO %ERRORLEVEL%

Мой обходной путь - использовать Grep из Cygwin, который выводит правильный уровень ошибки (он даст уровень ошибки больше 0), если строка не найдена:

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

grep Cygwin также выведет уровень ошибки 2, если файл не найден. Вот хеш из моей версии:

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...