2

Batch files in Windows can be confusing at the best of times. How does

  findstr "^"

equate to finding an empty folder, when ^ means the start of the line?

for /d /r %1 %%A in (.) do (
  dir /ad /b "%%~fA" 2>nul | findstr "^" >nul || echo %%~fA
)

taken from dbenham's answer

Unless I'm reading this wrong and it's

dir /ad /b "%%~fA" 2>nul

that finds empty folders.

Ghoul Fool
  • 6,249
  • 10
  • 67
  • 125
  • 2
    The provided link doesn't `dir /ad /B ...` It's just `dir /a /b...` to include also hidden,system attributes. `findstr "^"` will match any line and return no success to the conditional execution operator `||` if there is none. –  May 26 '19 at 19:17

2 Answers2

3

This script will get a list of directories (and their subdirectories), loop through each directory to check for subdirectories, then list only the directory names that did not contain a subdirectory. The original script in the link provided works similarly except that it will only list completely empty directories (not containing subdirectories or files). Here is a breakdown of each section of code:


The for /d in your example is getting a recursive list of directories:

for /d /r %1 %%A in (.) do ( )
  • for /d loops through the specified set of directories
  • for /d /r tells the for loop to recurse into subdirectories
  • %1 is an optional file path specified from the command-line
  • %%A will return the current directory in each loop
  • in (SET) specifies the directory set to loop through
  • Specifying "in (.)" tells for to loop through all directories

The code inside your for loop then checks each directory to see if it's empty*:

  dir /ad /b "%%~fA" 2>nul | findstr "^" >nul || echo %%~fA
  • dir /ad /b "PATH" gets a list of subdirectories in the specified path*
  • "%%~fA" expands the current directory name to its full path
  • 2>nul hides any dir errors by redirecting STDERR to nul
  • | pipes the list of subdirectories found by dir into findstr
  • findstr "^" then checks for a non-empty list of subdirectories
  • >nul hides the findstr results by redirecting all output to nul
  • || runs a command if the previous command failed (no findstr results)
  • echo %%~fA returns the directory name if no sub-directories were found*

*Please Note: as mentioned by LotPings, the code you provided will produce different results than in the example you linked to. dir /a /b lists all files and directories while dir /ad /b lists directories only. This means that your script will list all directories not containing a subdirectory (but that may still contain files). If this was the expected behavior, please disregard this note.

Edit: further broke down the above list of commands as suggested by Ben Voigt.

Seth McCauley
  • 983
  • 11
  • 24
  • 1
    I'm not sure why you're grouping redirection to nul together with `||`. For `|` it makes some sense because piping is a form of redirection. – Ben Voigt May 27 '19 at 03:28
  • Agreed. It could be confusing or misleading since there was no logical connection between those sections of the command. I'm not sure why I grouped them that way after I broke everything else down either. I have now updated my answer to further clarify this. Thank you. – Seth McCauley May 27 '19 at 14:45
2

I believe the piece of this that you're missing is the || (logical OR) operation.

It runs the command after it only if the preceding command fails.

Knowing this, it will make sense that dir /ad /b "%%~fA" 2>nul | findstr "^" >nul is not looking for empty directories. It is succeeding when the list generated by dir is NOT empty. It fails when the listing is empty.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720