Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Batch script to delete empty folders?

Posted on 2013-10-30
25
Medium Priority
?
3,184 Views
Last Modified: 2013-12-16
Hi all,

Following on from some excellent help from knightEknight on this script:
http://www.experts-exchange.com/Programming/Languages/Scripting/Shell/Batch/Q_28273418.html


I'm now in need of a script to recursively search for and delete empty folders.

so i have a root folders called:

+Media

This has say 3 folders, with one of the folders having a subfolder:

+Folder1
+Folder2
+Folder3
....+Folder3a

Only Folder2 has files in it, all of the others need to be deleted.


Any idea how to write a batch file to achieve this?

Thanks,
0
Comment
Question by:TheDadCoder
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 11
  • 8
  • 6
25 Comments
 
LVL 57

Expert Comment

by:Bill Prew
ID: 39612150
Here's a simple VBS script that can be used to do what you described, save as a VBS and update the base dir path at the top.

It currently prints the folders it removes, but if you want it to run silently just remove the Wscript.Echo line.

Const strBaseDir = "C:\EE\EE28281260\Files"

set objFSO = WScript.CreateObject("Scripting.FileSystemObject")

RemoveFolder objFSO.GetFolder(strBaseDir)

Sub RemoveFolder(objFolder)
    For Each objSubFolder In objFolder.Subfolders
        RemoveFolder objSubFolder
    Next
    If objFolder.Files.Count = 0 And objFolder.Subfolders.Count = 0 Then
        Wscript.Echo objFolder.Path
        objFolder.Delete
    End If
End Sub

Open in new window

~bp
0
 
LVL 26

Expert Comment

by:wilcoxon
ID: 39612198
If you have cygwin or other Unix environment installed on your Windows then you can do it with a very simple shell command.
find . -depth -type d -empty -exec rmdir {} \;

Open in new window


I was going to use find2perl to generate a perl script to do it but apparently find2perl doesn't support -empty so it becomes more difficult...
0
 

Author Comment

by:TheDadCoder
ID: 39620229
Hi billprew - thanks I'll try that script.

Hi wilcoxon, I'm not using cygwin or any unix system here, thanks anyway.
0
Give Your Engineering Team a Productivity Boost

Learn why container technology is so powerful and how it can provide your team with productivity gains and other benefits.

 

Author Comment

by:TheDadCoder
ID: 39624752
Hi billprew, I've tested your vbs script and for normal files it works, of course.

However, I've noticed that some folders that appeared empty it failed to delete them.  upon inspection this was due to hidden files, such as thumbs.db.

Any ideas how it can still delete if it finds a file that's to delete?

or is it just easier to do a windows find and delete first?
0
 
LVL 26

Expert Comment

by:wilcoxon
ID: 39624948
It depends.  Are all the files in the "empty" directories 0-size files so should be removed by the script?  If so, you need to do a depth-first traversal so it will see the 0-size files before it checks if the directory is empty.
0
 

Author Comment

by:TheDadCoder
ID: 39625118
Hi - no these are system files that store icon pos values, and other stuff, which in this situation are not needed.

I'm thinking a list of files to always delete... but it might just be easier to delete these via windows search first.
0
 
LVL 26

Expert Comment

by:wilcoxon
ID: 39625499
A list of filenames to always delete or to delete only if they are the only files in a folder (eg leave alone if the folder is not otherwise empty) should work fine.  I should have time tomorrow sometime to work up a perl solution...
0
 
LVL 57

Expert Comment

by:Bill Prew
ID: 39626161
Sounds like it might be easiest, and safest, to just delete the desired files, and then run the script to remove the empty folders.

~bp
0
 
LVL 26

Expert Comment

by:wilcoxon
ID: 39626515
Here's a perl solution...
use strict;
use warnings;
use File::Find ();

# for the convenience of &wanted calls, including -eval statements:
use vars qw/*name *dir *prune/;
*name   = *File::Find::name;
*dir    = *File::Find::dir;
*prune  = *File::Find::prune;

use Cwd ();
my $cwd = Cwd::cwd();

my $base = shift || 'C:/EE/EE282281260/Files'; # pass in or default

# change this to include the files you want to remove if they are the
# only ones in the directory
my @files_to_rm = (qw(thumbs.db anotherfile and_another));
my %files_to_rm = map { $_ => 1 } @files_to_rm;

# Traverse desired filesystems
File::Find::finddepth({wanted => \&wanted}, $base);
exit;

sub wanted {
    my ($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_);
    if (-f _ and int(((-s _) + 511) / 512) == 0) {
        unlink $name or die "could not rm $name: $!";
    } elsif (-d _) {
        opendir DIR, $name or die "could not open dir $name: $!";
        my @files = grep !m{^\.+$}, readdir DIR;
        closedir DIR;
        my @del = grep { exists $files_to_rm{$_} } @files;
        # there are no files or all files are ones to remove
        if (@files == @del or @files == 0) {
            foreach my $fil (@files) {
                unlink "$name/$fil" or die "could not rm $name/$fil: $!";
            }
            system('rmdir', $name) == 0 or die "rmdir failed: $?";
        }
    }
}

Open in new window

0
 
LVL 57

Expert Comment

by:Bill Prew
ID: 39649975
Give this a try:

Const strBaseDir = "C:\EE\EE28281260\Files"

arrFilesToDelete = Array("thumbs.db", "desktop.ini")

set objFSO = WScript.CreateObject("Scripting.FileSystemObject")

RemoveFolder objFSO.GetFolder(strBaseDir)

Sub RemoveFolder(objFolder)
    For Each objSubFolder In objFolder.Subfolders
        RemoveFolder objSubFolder
    Next
    For Each objFile in objFolder.Files
        For Each strFileToDelete in arrFilesToDelete
            If LCase(strFileToDelete) = LCase(objFile.Name) Then
                objFile.Delete(True)
            End If
        Next
    Next
    If objFolder.Files.Count = 0 And objFolder.Subfolders.Count = 0 Then
        Wscript.Echo objFolder.Path
        objFolder.Delete
    End If
End Sub

Open in new window

~bp
0
 

Author Comment

by:TheDadCoder
ID: 39654394
Another script to test :)
0
 
LVL 26

Expert Comment

by:wilcoxon
ID: 39661341
Just wondering if you've had time to test the perl script I submitted?  If so, any issues with how it worked?
0
 

Author Comment

by:TheDadCoder
ID: 39680972
Hi wilcoxon - how do you run the perl script?

billprew - yours works as needed thanks.
0
 

Author Comment

by:TheDadCoder
ID: 39681031
Hi billprew,

I added an additional filename to the script as below but I get an error now.   I guess it doesn't like the mac os filename '.DS_Store'?


Any ideas?

invalid procedure call or arguement
code: 800A0005
Line: 21:
char: 8


Const strBaseDir = "v:\"

arrFilesToDelete = Array("thumbs.db", "desktop.ini", ".DS_Store")

set objFSO = WScript.CreateObject("Scripting.FileSystemObject")

RemoveFolder objFSO.GetFolder(strBaseDir)

Sub RemoveFolder(objFolder)
    For Each objSubFolder In objFolder.Subfolders
        RemoveFolder objSubFolder
    Next
    For Each objFile in objFolder.Files
        For Each strFileToDelete in arrFilesToDelete
            If LCase(strFileToDelete) = LCase(objFile.Name) Then
                objFile.Delete(True)
            End If
        Next
    Next
    If objFolder.Files.Count = 0 And objFolder.Subfolders.Count = 0 Then
       objFolder.Delete
    End If
End Sub

Open in new window

0
 

Author Comment

by:TheDadCoder
ID: 39681056
Hi billprew - ignore my last comment.  It deletes the files with the new filename fine, however the error seems to come from the delete command when the basedir is empty, i.e. nothing to delete, but it tries to delete anyway, but since there's nothing to delete it fails.

Not a major issue, but it'd be nice to return an message saying "Nothing to delete!", or something.

Is this possible?
0
 
LVL 57

Expert Comment

by:Bill Prew
ID: 39681176
So are you saying there are no files or folders under v:\, but it is trying to delete v:\? Naturally deleting a root folder of a drive will fail, that's not allowed, but I'm surprised you are actually empty on v:\?

We would actually want to check the folder name I suspect, and handle this special case, the root folder, if that's what you are seeing.

~bp
0
 
LVL 26

Expert Comment

by:wilcoxon
ID: 39681448
Sorry.  You had posted in the Perl topic so I assumed you knew how to run Perl...

In order to run a perl script, you need to have perl installed.  If you are on Mac, I'm pretty sure it is standard.  If you are on Windows then you probably need to install one - I'd suggest Strawberry Perl.

Once it is installed, you should be able to type "perl <script name> <script arguments>" (replacing the items in <> with the actual names/values).  If you are on Windows, you'll likely need to open "Perl (command line)" (or something similar) rather than the normal command prompt to run it (I'm not sure why it gets installed that way as I believe the only difference is some environment variables).
0
 

Author Comment

by:TheDadCoder
ID: 39692089
Hi billprew,  v: drive is just a mapped drive to my polling folder, nothing special.  The end result would be that folder, that v drive points to, is empty.  or not empty and i know i have files i need to clear out manually.

I don't know if it's trying to delete v drive, but the code looks like it's running the delete command but i suspect there's nothing to delete.

This is confusing because your last section eval's if files and folder count =0.
0
 
LVL 57

Accepted Solution

by:
Bill Prew earned 2000 total points
ID: 39694483
Thy this small workaround.

Const strBaseDir = "v:\"

arrFilesToDelete = Array("thumbs.db", "desktop.ini", ".DS_Store")

set objFSO = WScript.CreateObject("Scripting.FileSystemObject")

RemoveFolder objFSO.GetFolder(strBaseDir)

Sub RemoveFolder(objFolder)
    For Each objSubFolder In objFolder.Subfolders
        RemoveFolder objSubFolder
    Next
    For Each objFile in objFolder.Files
        For Each strFileToDelete in arrFilesToDelete
            If LCase(strFileToDelete) = LCase(objFile.Name) Then
                objFile.Delete(True)
            End If
        Next
    Next
    If objFolder.Files.Count = 0 And objFolder.Subfolders.Count = 0 Then
       If Len(objFolder.Path) > 3 Then
           objFolder.Delete
       End If
    End If
End Sub

Open in new window

~bp
0
 

Author Closing Comment

by:TheDadCoder
ID: 39721338
Just perfect, thank you.
0
 
LVL 26

Expert Comment

by:wilcoxon
ID: 39721467
Why no recent comments about my script and no splitting of the points?  The perl script I submitted did exactly what you requested.
0
 

Author Comment

by:TheDadCoder
ID: 39721992
Hi  wilcoxon,

I thank you for assistance, however I voted to use the alt script as it was quicker to just use, rather than install perl.

Thanks anyway.
0
 
LVL 26

Expert Comment

by:wilcoxon
ID: 39722130
May I suggest, in future, not including the "Perl Programming Language" topic if you don't want to install Perl?
0
 

Author Comment

by:TheDadCoder
ID: 39722152
you may.
0
 
LVL 57

Expert Comment

by:Bill Prew
ID: 39722227
Welcome.

~bp
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article will show, step by step, how to integrate R code into a R Sweave document
Originally, this post was published on Monitis Blog, you can check it here . In business circles, we sometimes hear that today is the “age of the customer.” And so it is. Thanks to the enormous advances over the past few years in consumer techno…
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …
In this fifth video of the Xpdf series, we discuss and demonstrate the PDFdetach utility, which is able to list and, more importantly, extract attachments that are embedded in PDF files. It does this via a command line interface, making it suitable …

715 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question