forfiles error suppression not working as expected

4k views Asked by At

I want to delete files from a folder and if there are no files to delete, error should be ignored and all the other errors should be captured. Below is the code I am using.

FOR /F "tokens=*" %%a IN ('FORFILES /P "%%G" /D -3 /C "cmd /c DEL @path" 2^>^&1 ^| FINDSTR ERROR') DO SET _CmdResult=%%a

IF "%_CmdResult%" == "ERROR: No files found with the specified search criteria." ( 

    SET errorlevel=0 

 ) ELSE ( 

    SET errorlevel=1

)

IF "%_CmdResult%" == "NONE" SET errorlevel=0

IF NOT %errorlevel% EQU 0 ( 

goto delete_fail )

Below is what I see on command prompt when I run above code.

FOR /F "tokens=*" %a IN ('FORFILES /P "%G" /D -2 /C "cmd /c DEL @path" | FINDSTR ERROR') DO SET _CmdResult=%a

 IF "NONE" == "ERROR: No files found with the specified search criteria." <<<<< _CmdResult is still "NONE"

(

SET errorlevel=0  

)  ELSE (

SET errorlevel=1 )

 IF "NONE" == "NONE" SET errorlevel=0

 IF NOT 0 EQU 0 (goto delete_fail  )

Based on the log I found that error string is not getting saved into _CmdResult when there are not files to delete. Can anyone let me know what I am missing,

3

There are 3 answers

0
MC ND On
FOR /F "tokens=*" %%a IN ('FORFILES /P "%%G" /D -3 /C "cmd /c DEL @path" 2^>^&1 ^| FINDSTR ERROR') DO SET _CmdResult=%%a

The %%G indicates this line is executed as part of an outer for loop. If that loop includes the rest of the code shown, then you have a problem with delayed expansion. When execution reaches a block (code between parenthesis), all lines are parsed before execution, and the lines in which variables are readed are changed, replacing the reference to the variable with the value it contains at the time of parsing of the block. You will need to enable delayed expansion and instead of %var% sintax, use the !var! sintax.

IF "%_CmdResult%" == "ERROR: No files found with the specified search criteria." ( 
    SET errorlevel=0 
) ELSE ( 
    SET errorlevel=1
)
IF "%_CmdResult%" == "NONE" SET errorlevel=0

In short, don't do that. Don't set the errorlevel variable to any value. Its value is dynamic, provided by cmd when readed, but, if a value is explicitly assigned, the dynamic value can not be read. %errorlevel% will return the value you set to it. If you set it to 0, you will only get this value, independly of sucess of failure of commands. It will be 0.

If you need to reset the errorlevel value, use something like vol > nul

1
foxidrive On

Use this command before your code above and branch on the errorlevel

FORFILES /P "%%G" /D -3 2>&1 |find "ERROR:" >nul
if errorlevel 1 goto :nofiles
FORFILES /P "%%G" /D -3 /C "cmd /c DEL @path"
0
U12 On

I tried with below code and it is working as expected. Earlier I missed pasting the outer for loop and sorry for that. I have enabled delayed expansion and with help of that I am able to achieve my requirement.

SET del_op=NONE



rem ###################################
rem - Loop thru all archives to delete
rem ###################################
FOR %%G in (%arc_log%,%arc_in%,%arc_out%) DO ( 

ECHO Deleting files from "%%G" older than %var% days  >> %log_path%\%log_file% 2>>&1

FOR /F "tokens=*" %%a IN ('FORFILES /P "%%G" /D -%var% /C "cmd /c DEL @path" 2^>^&1 ^| FINDSTR ERROR') DO SET del_op=%%a

rem ####################
rem - suppressing error
rem ####################

IF "!del_op!" == "ERROR: No files found with the specified search criteria." ( 
   ECHO suppressed "!del_op!" >> %log_path%\%log_file% 2>>&1
    SET err_lv=0 
 ) ELSE ( 
    SET err_lv=1
)

IF "!del_op!" == "NONE" SET err_lv=0

IF !err_lv! EQU 1 ( 
goto delete_fail )
ECHO Successfully deleted old files from "%%G" >> %log_path%\%log_file% 2>>&1
)

Thanks all for your suggestions.