Как условно принять меры, если FINDSTR не сможет найти строку
У меня есть пакетный файл следующим образом:
CD C:\MyFolder
findstr /c:"stringToCheck" fileToCheck.bat
IF NOT XCOPY "C:\OtherFolder\fileToCheck.bat" "C:\MyFolder" /s /y
Я получаю сообщение об ошибке ( "C:\OtherFolder\fileToCheck.bat" было неожиданным в настоящее время.) при попытке выполнить это.
Пожалуйста, дайте мне знать, что я делаю неправильно.
Ответы
Ответ 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