it-swarm-pt.tech

Como executar uma ação condicional se FINDSTR falhar ao encontrar uma sequência

Eu tenho um arquivo em lotes da seguinte maneira;

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

Estou recebendo um erro ("C:\OtherFolder\fileToCheck.bat" foi inesperado no momento.) Ao tentar executar isso.

Por favor, deixe-me saber o que estou fazendo de errado.

24
testndtv

Você não está avaliando uma condição para o FI. Eu estou supondo que você deseja não copiar se você encontrar stringToCheck em fileToCheck. Você precisa fazer algo como (código não testado, mas você entendeu):

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

EDITAR por dbenham
O teste acima está ERRADO, sempre é avaliado como FALSO.
O teste correto é IF ERRORLEVEL 1 XCOPY ...

Atualização: não consigo testar o código, mas não tenho certeza de qual valor de retorno findstr realmente retornará se não encontrar nada. Você pode ter que fazer algo como:

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
10
Luke Kim

Suponho que você deseja copiar C:\OtherFolder\fileToCheck.bat para C:\MyFolder se o arquivo existente em C:\MyFolder estiver totalmente ausente ou se estiver faltando "stringToCheck".

FINDSTR define ERRORLEVEL como 0 se a sequência for encontrada e 1 se não for. Ele também define o nível de erro como 1 se o arquivo estiver ausente. Também imprime cada linha que corresponde. Como você está tentando usá-lo como uma condição, presumo que você não precisa ou deseja ver nenhuma saída. A primeira coisa que eu sugeriria é redirecionar a saída normal e de erro para nul usando >nul 2>&1.

Solução 1 (principalmente o mesmo que as respostas anteriores)

Você pode usar IF ERRORRLEVEL N para verificar se o nível de erro é> = N. Ou você pode usar IF NOT ERRORLEVEL N para verificar se o nível de erro é <N. No seu caso, você deseja o primeiro.

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

Solução 2

Você pode testar um valor específico de errorlevel usando% ERRORLEVEL%. Provavelmente, você pode verificar se o valor é igual a 1, mas pode ser mais seguro verificar se o valor não é igual a 0, pois ele é definido como 0 apenas se o arquivo existe e contém a sequência.

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

ou

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

Solução

Há uma sintaxe muito compacta para executar condicionalmente um comando com base no sucesso ou falha do comando anterior: cmd1 && cmd2 || cmd3 que significa executar o cmd2 se o cmd1 tiver êxito (nível de erro = 0); caso contrário, execute o cmd3 se o cmd1 falhar (nível de erro <> 0). Você pode usar && sozinho ou || sozinho. Todos os comandos precisam estar na mesma linha. Se você precisar executar condicionalmente vários comandos, poderá usar várias linhas adicionando parênteses

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

Então, para o seu caso, tudo que você precisa é

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

Mas cuidado - o || responderá ao código de retorno do último comando executado. No meu pseudo-código anterior, o || será acionado obviamente se o cmd1 falhar, mas também será acionado se o cmd1 for bem-sucedido, mas o cmd3 falhar.

Portanto, se o seu bloco de sucesso terminar com um comando que pode falhar, você deve anexar um comando inofensivo que tenha sucesso garantido. Eu gosto de usar (CALL ), que é inofensivo e sempre é bem-sucedido. Também é útil definir o ERRORLEVEL como 0. Há um corolário (CALL) que sempre falha e define ERRORLEVEL como 1.

66
dbenham

No DOS/Windows Batch, a maioria dos comandos retorna um exitCode, chamado "errorlevel", que é normalmente um valor igual a zero se o comando terminar corretamente ou um número maior que zero se terminar devido a um erro, com números maiores para erros maiores (daí o nome).

Existem alguns métodos para verificar esse valor, mas o original é:

IF ERRORLEVEL value command

Teste IF anterior, se o nível de erro retornado pelo comando anterior foi maior que OR IGUAL ao valor especificado e, se isso for verdadeiro, execute o comando. Por exemplo:

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

O comando Findstr retorna 0 se a cadeia foi encontrada e 1 se não:

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

O código anterior copiará o arquivo se a sequência NÃO for encontrada no arquivo.

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

O código anterior copia o arquivo se a sequência foi encontrada. Tente o seguinte:

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

Tentei fazer isso funcionar com FINDSTR, mas por algum motivo meu comando "debugging" sempre gera um nível de erro 0:

ECHO %ERRORLEVEL%

Minha solução alternativa é usar o Grep do Cygwin, que gera o nível de erro correto (ele fornecerá um nível de erro maior que 0) se uma string não for encontrada:

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

O grep do Cygwin também exibirá o nível de erro 2 se o arquivo não for encontrado. Aqui está o hash da minha versão:

C:\temp\temp> grep - versão grep (GNU grep) 2.4.2

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

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

0
Justin Goldberg