user2832776
user2832776

Reputation: 31

batch script to delete every other file in directories

I have a directory with many sub-directories that contain thousands of jpgs. What I want to do is create a batch script that will go through all of the sub-directories and delete every 2nd image i.e. keep the first, third, fifth image but delete the second, fourth, and six image etc per directory (ordered by filename).

I tried with the following but my knowledge of batch scripting is poor, and the syntax is clearly incorrect.

@echo off
set z = 0
for /f %%a in ('dir/b *.jpg')
do (
  set z = z + 1
  if z == 2 del %%a
)

Upvotes: 3

Views: 2478

Answers (2)

dbenham
dbenham

Reputation: 130819

  • The DO must be on the same line as FOR.

  • You must use SET /A if you want to do math

  • Your logic is wrong - Currently it will only delete the 2nd file, not every other one. You should take the mod 2 value (remainder devided by 2) and delete if the result is 0.

  • You must use %z% if you want to see the current value (except within a SET /A statement). But that will not work inside a code block that just set the value. In that case you need to enable delayed expansion and use !z! instead.

  • Expanding a FOR variable that contains ! (valid in file names) while delayed expansion is enabled will corrupt the value. So delayed expansion must be toggled on and off

  • You say you want to recurse sub-directories, but your code only looks at one folder.

  • Spaces are significant in the SET statement. Your code defines a variable z with a space at the end of the name. Not what you want.

Here is a debugged version:

@echo off
setlocal
for /r %%D in (.) do (
  set "z=0"
  for /f %%F in ('dir /b "%%D\*.jpg"') do (
    set /a "z+=1, r=z%%2"
    setlocal enableDelayedExpansion
    if !r! equ 0 del "%%D\%%F"
    endlocal
  )
)

There are ways to solve this without delayed expansion. One is to simply alternate between defining and undefining a variable.

@echo off
setlocal
for /r %%D in (.) do (
  set "del="
  for /f %%F in ('dir /b "%%D\*.jpg"') do if defined del (
    del "%%D\%%F"
    set "del="
  ) else set "del=1"
)

Another is to intentionally divide by 0 when you want to delete, and delete only when there is an error. Error messages are hidden by 2>nul, and the || operator conditionally executes the following command only if the prior command failed.

@echo off
setlocal
for /r %%D in (.) do (
  set "z=0"
  for /f %%F in ('dir /b "%%D\*.jpg"') do 2>nul set /a "z+=1, 1/(z%%2)" || del "%%D\%%F"
)

Upvotes: 5

Endoro
Endoro

Reputation: 37569

try this and remove the echo if the output looks good:

@echo off &setlocal
for /f "tokens=1*delims=:" %%a in ('dir /b /s /a-d *.jpg^|findstr /n $') do (
    echo %%a|findstr "[02468]$" >nul && echo del "%%~b"
)

Upvotes: 1

Related Questions