views:

452

answers:

8

Hello, i have the following code in batch (cmd):

for /f "delims=" %%f in ('dir /b /s Example') do (
command
if %errorlevel%==1 (
command
SKIP
)
command
)

EDIT: To make things more clear: for /f... searches for a directory called 'Example' and loops to search for more directories than one. the first command is a delete command, it deletes all files in the directory. the command that happens when an error occurs, is a echo command which writes some info about the error to a text file. now the hole skip thing; sometimes, the files can't be deleted because of access denied or this file is in use by.... Normally, what would happen if there weren't a skip thing, it would just stop the command and hang. So, what i want to do, is prevent this from happening. Alternatively, i want to use something like skip, so it can skip the file and continue anyways. So i think this command needs to be piped in the delete command.

I hope it's clear now.

Thanks in advance.

+3  A: 

Like this?

for /f "delims=" %%f in ('dir /b /s Example') do (
  command
  if not errorlevel 1 (
    command-for-success
  ) else (
    command-for-error
  )
)
atzz
Joey
@Johannes -- wow, i didn't know about "||"! Looks like a neat way to write short alternatives.
atzz
this does not really what i want. i want to let for skip it, and continue. what the command does, it looks for 'example', and then deletes everything in that directory. The problem is that you can't really easy 'skip' it.
YourComputerHelpZ
i edited my question so you can maybe understand it now.
YourComputerHelpZ
In batch scripts, you can also use `goto`.
Pekka
@YourComputerHelpZ: this solution indeed skips "command-for-success" when an error occurs, executes "command-for-error" instead, and continues with the next file in 'example'. Please explain better what you think what is missing.
Doc Brown
A: 

I believe that this is what you want

for /f "delims=" %%f in ('dir /b /s Example') do (
  command
  if not errorlevel 1 (
    command
  ) else (
    command
    goto :eof
  )
)
PA
this is the same as @atzz, again, read the comments, i dont like that kind of stuff.
YourComputerHelpZ
that was my best attempt trying to understand what you mean by "skip". Make some effort to improve your explanation, because if you don't you just cast doubt on the amount you really value a good answer. Your lack of interest on getting understood only rivals your rudeness.
PA
+2  A: 

Create the two command files and run delex.cmd. The files and directories that are not deleted will be logged to delex.txt. The ones that hang, will have a minimized cmd window open that gets killed after a delay by using ping (thanks to Doc Brown's suggestion).

delex2.cmd
----------
@echo off
del /q %1 
if exist %1 echo %1 not deleted!>>delex.txt 
exit 

delex.cmd
---------
@echo off
if exist delex.txt del delex.txt 
for /f "delims=" %%f in ('dir /s /b example') do start "delextaskkill" /min delex2.cmd "%%f"
ping 127.0.0.1 -n 3 -w 1000> nul
taskkill /fi "Windowtitle eq delextaskkill"> nul

Tested with:

\example
|   file1
|   file2
|   file3
|   file4
|   file5
|
\---example
        file1
        file2
        file3
        file4
        file5
fupsduck
I think this one can be improved to close all 'hanging' windows afterwards after a given timeout. Add a special windowtitle to the 'start' command. Use http://malektips.com/dos0017.html to simulate a "Wait" command (for example, wait for 10 seconds afterwards), and use taskkill /fi "Windowtitle eq <YourSpecialWindowtitle>" to kill all hanging windows.
Doc Brown
great suggestion Doc - it works!
fupsduck
+1 for getting my additional suggestion working!
Doc Brown
A: 

Perhaps this is more advanced than can be accomplished using just built-in cmd processing. Why not consider using the Windows Scripting Host (vbscript/jscript) or even PowerShell? Both will likely provide you the level of control you are requesting.

Goyuix
+1  A: 

When one uses del, and "access denied" or "this file is in use by..." occurs, %errorlevel% is 0, so testing %errolevel% is useless. Perhaps the following simple solution works in your case:

for /f "delims=" %%f in ('dir /b /s Example') do (
    del %%f
    if exist %%f (
         echo "file not deleted"
    ) else (
         echo "file deleted"
    )
 ) 
Doc Brown
but it wouldn't skip, does it?
YourComputerHelpZ
I tried it with 3 files in a directory 'Example', one write protected and two in use, and I get 3 times "file not deleted". If this is not what you mean by 'skip', please give a better example or explanation.
Doc Brown
+1 for your suggestion.
fupsduck
A: 

Try this batch file:

@echo off
REM For each directory named 'Example' ...
for /f "delims=" %%f in ('dir /b /s Example') do (
    REM .. enter the directory and delete all the files found there.
    pushd .
    cd %%f
    del /q *
    for /f "delims=" %%z in ('dir /b') do (
        REM Any files that still exist must have been inaccessable.  Log an error.
        echo Unable to delete file %%z > C:\logfile.txt
    )
    popd
)

Tested with the following directory structure:

folder\
|------Example\
|      |-------file1 (write-protected)
|      |-------file2
|      |-------file3
|------deeper\
       |-------Example\
               |-------file4
               |-------file5 (write-protected)
               |-------file6

After running the batch file, only file1 and file5 were left. An "Access is denied" message was printed for each write-protected file encountered; if that gets annoying you re-direct the output of the batch file like script.bat > NUL to hide it.

bta
A: 

So after all the existing answers didn't satisfy you and you absolutely need a skip within your batch file, i will make another try:

@echo off
setlocal

for /f "delims=" %%f in ('dir /b /s batch') do call :DoSomething %%f
goto end

:DoSomething
echo Here i am: %1
if %errorlevel%==1 goto :eof

echo No error occured
goto :eof

:end
endlocal

The trick is, that the for loop calls a sub function within the same file and gives the needed parameter to it. This new call runs in a new context and can only access the variables which are defined after the do call :DoSomething in the given order their.

So you have to access the variables here with %1, %2, etc. If you want to leave this context you have to make a goto :eof to jump to the end of the file (this marker is predefined in batch mode and should not occur within your file), what leaves the context and returns to the for loop.

After running through the whole loop we just jump to the :end marker, make a little clean up and are finished.

Oliver
A: 

The following looks for the file extentions you want recursively under the "dirname" directory tree and executes commandstuff.bat against that file name:

for /r %i in (c:\dirname\*.ext) do commandstuff "%i"

Commandstuff.bat looks like this:

@ECHO OFF
del %1
IF (%ERRORLEVEL% == 0) goto END
:ERROR
Echo Error deleting %1

:END
Echo end

This would run commandstuff.bat for you to delete the files you want. When there is an error it will simply echo the file details and continue processing the next file.

Ameer Deen