0

In a *NIX system, you can easily type rmdir * to remove all empty directories in .. rmdir will complain about non-empty directories and not delete them.

Basically, if you have a tree like this:

/
  d0/
    file
  d1/
    d0/
  d2/
  d3/

Then running rmdir * from within / will result in d2/ and d3/ being deleted only. d0/ and d1/ will be left alone with an error echoed about them being non-empty, so as to prevent the contents from being lost in limbo.

/
  d0/
    file
  d1/
    d0/

I have not been able to find a Windows equivalent to this. The closest thing is rmdir /s ., which is equivalent to rm -r ., except it refuses to delete . because the shell is using it. Not sure if rm -r . also refuses to delete .. Haven't tested that.

Like *NIX rmdir, Windows rmdir will refuse to delete a single directory if non-empty. However, there doesn't seem to be a wildcard selector like the typical *, which is strange because that token can be used anywhere else.

It's this kind of stuff that frustrates me with the Windows command line. If I have 4,000 directories, rmdiring every single directory explicitly is obviously not a sane option. There must be a better way.

I've tried building a for statement according to the syntax in the usage help (for /?)

FOR %variable IN (set) DO command [command-parameters]

...to get...

for %f in * do rmdir %f

and several variations of that (like changing the second %f to %f%, all-caps'ing the syntax even though I know it's case-insensitive, surrounding * with parens, et al). None of which worked. All failing with unexplained and unhelpful errors like:

%f was unexpected at this time.
* was unexpected at this time.

(NB: I'm attempting this on the interactive prompt, not in a script)

Or in the case of the (*) variation...

>for %f in (*) do rmdir %f
>rmdir file
The directory name is invalid.
>dir
 Volume in blah blah blah

 Directory of blah

 blah blah    <DIR>          .
 blah blah    <DIR>          ..
 blah blah    <DIR>          nonemptydir
 blah blah    <DIR>          emptydir
 blah blah                 1 file
     1 File(s)             1 bytes
     4 Dir(s)    huge number bytes free

...it doesn't even touch the directories.

I don't understand why it would do that. I followed the syntax as it was described in the help.

Powershell is not an option. I need to be able to do this in a shell that is guaranteed to be installed, i.e. cmd.exe. Jeff Zeitlin informed me that Powershell is guaranteed >= Windows 7. However, cmd.exe is still preferred.

5
  • For Windows 7 and later, or Windows Server 2008R2 or later, PowerShell is guaranteed to be installed - Windows 7 comes with PowerShell 2; Windows 8 comes with PowerShell 3, Windows 8.1 comes with PowerShell 4, and Windows 10 comes with PowerShell 5. The corresponding Windows Server versions come with the corresponding versions of PowerShell. For your for statement, I recommend you bookmark ss64.com/nt as an excellent reference for cmd. Specifically, in for %i in (*) do ..., the parentheses are mandatory. – Jeff Zeitlin Jul 11 '17 at 17:46
  • What version of Windows? If you have Windows 10 you could in theory literally use that command if you use WSL. – Ramhound Jul 11 '17 at 17:49
  • @JeffZeitlin okay, doesn't help if I find myself on a Windows XP box, but I digress. for %f in (*) do rmdir %f was one of the failed variations I tried. I have a test directory with an empty dir, a non-empty dir, and a plain, extension-less file. It echoes rmdir file, and then gives the error The directory name is invalid.. No directories end up being removed. It seems to give up on the error – Braden Best Jul 11 '17 at 17:50
  • I'm surprised at this late date that there's any XP still left around, but OK. As far as the for statement, I again refer you to SS64, specifically SS64 on FOR for folders. Note that Winbatch is an evolving language even today; you really do need to find a reference that's specific to XP if you truly need to support it. – Jeff Zeitlin Jul 11 '17 at 17:55
  • @JeffZeitlin TBH, I don't expect to run into an XP machine. Just me giving you a hard time. Anyways, I took a look at the reference you linked. You should post it as an answer. What worked for me was for /d %d in (*) do rmdir %d, which removes the empty directory, ignores the file, and leaves the non-empty directory alone, exactly as *NIX's rmdir * does. – Braden Best Jul 11 '17 at 18:00
2

Your FOR statement wants the /D switch: FOR /D %I in (*) do .... This causes files to be skipped entirely, and only folders (directories) to be processed. Since RMDIR/RD won't remove a non-empty directory, this appears to be what you want; note that different versions of Windows may react differently to the error of attempting to remove a non-empty directory.

References: SS64 on FOR and FOR /D (FOR for Folders)

2
  • There we go. That's the copper-plated zinc bullet I was looking for. – Braden Best Jul 11 '17 at 18:12
  • 1
    FWIW, this is one of the few cases I've encountered where the CMD solution was actually better/easier than the PowerShell solution. – Jeff Zeitlin Jul 11 '17 at 18:15
2

%f was unexpected at this time. * was unexpected at this time.

for %f in * do rmdir %f

When used inside a batch file you need to double up the %s.

The set you refer to is an expression in parentheses. The parentheses are not optional.

Corrected command line:

for %f in (*) do rmdir %f

Correct batch file:

for %%f in (*) do rmdir %%f

This is documented in the online help:

> for /?
Runs a specified command for each file in a set of files.

FOR %variable IN (set) DO command [command-parameters]

  %variable  Specifies a single letter replaceable parameter.
  (set)      Specifies a set of one or more files.  Wildcards may be used.
  command    Specifies the command to carry out for each file.
  command-parameters
             Specifies parameters or switches for the specified command.

To use the FOR command in a batch program, specify %%variable instead
of %variable.  Variable names are case sensitive, so %i is different
from %I.

And in for:

If you are using the FOR command at the command line rather than in a batch program, use just one percent sign: %G instead of %%G.

FOR Parameters

The first parameter has to be defined using a single character, for example the letter G.

FOR %%G IN ...

1
  • I appreciate the information on for, but this doesn't answer the question. – Braden Best Jul 11 '17 at 17:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.