Подтвердить что ты не робот

Как условно принять меры, если FINDSTR не сможет найти строку

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

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

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

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

4b9b3361

Ответ 1

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

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

EDIT by dbenham
Вышеуказанный тест НЕПРАВИЛЬНО, он всегда оценивает FALSE.
Правильный тест 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

Ответ 2

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

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

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

Вы можете использовать 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"

Решение 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). Вы можете использовать && один, или || в одиночестве. Все команды должны быть в одной строке. Если вам нужно условно выполнить несколько команд, вы можете использовать несколько строк, добавив круглые скобки

cmd 1 && (
   cmd2
   cmd3
) || (
   cmd4
   cmd5
)

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

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

Ответ 3

В DOS/Windows Batch большинство команд возвращают exitCode, называемый "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
)

Ответ 4

Я попытался заставить это работать с помощью 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"

Cygwin grep также выдает errorlevel 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