Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
)
like image 485
user2832776 Avatar asked Dec 02 '25 21:12

user2832776


1 Answers

  • 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"
)
like image 102
dbenham Avatar answered Dec 05 '25 13:12

dbenham



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!