Solved

Deleting

Posted on 2000-03-11
30
189 Views
Last Modified: 2010-03-05
How can I delete a folder specified on my server, and all the files in it?
0
Comment
Question by:cdc_sickle
  • 13
  • 6
  • 5
  • +2
30 Comments
 
LVL 16

Expert Comment

by:maneshr
Comment Utility
try this.

i am assuming you are working on a UNIX based system.
the same code with slight changes would work for a Windows based system too!!

===========my_delete.pl
#!/usr/bin/perl

print qq{
Usage: $0 <directory1> <directory 2> ....
  - Removes ALL files in that directory
} if $#ARGV<0;
   
$DEBUG=0;

foreach $dir (@ARGV){
  push @dir,$dir;
 
  while ($dirs=pop @dir){
    $whereami=`pwd`;
    chomp($whereami);
    chomp($dirs);
    chdir $dirs;
    print "CHANGING to $dirs\n";
     
    while (<*>) {
      next if ($_ eq ".");
      next if ($_ eq "..");
      if (-d $_) {  ##  This entry is a directory, ignore it!!
        next if (-l $_);
        print "\t Dir-> ",$_,"\n" if $DEBUG;
        #push @dir,$dirs."/".$_;
      } elsif (-l $_) { ##  This entry is a SYMBOLIC LINK file, ignore it!!

       next;
      } elsif (-f $_) { ##  This entry is a PLAIN file, pick it!!
        print "\t Deleting File-> ",$_,"\n" if $DEBUG;

        ##  Try and delete the file
        $count=unlink $_;
        if ($count){  ##  YESSS!! File was deleted
          print "$_ Deleted!!\n";
        }else{
          print "$_ NOT Deleted!!\n";

        }
      }
    }
    exit if $DEBUG;
    chdir $whereami;
  }
============================
0
 
LVL 3

Accepted Solution

by:
jyu_88 earned 100 total points
Comment Utility
`unlink` to delete file
`rmdir` to remove empty folder.
So, to do what you want, you'd implement a sub, which has recursive call to itself to remove file inside it first then remove the folder.

sub RemoveDir() {
my $rootDir = $_[0];
my @dirEnt = ();
return -1 unless -d $rootDir;
opendir TOGODIR, $rootDir or return -1;
@dirEnt = grep !/\.\.?$/, readdir TOGODIR;
foreach $ent(@dirEnt) {
$ent = $rootDir."/".$ent;
if ( -f $ent) { unlink $ent }
if ( -d $ent) { &RemoveDir($ent) }
}
return 0
}


or you can use system("rm", "-rf", "togofolder") to use whatever command available from the operating system.
0
 

Author Comment

by:cdc_sickle
Comment Utility
for both of you... What variable to i use to tell it which directory to delete?
0
 
LVL 84

Expert Comment

by:ozo
Comment Utility
use File::Path;
rmtree(['foo/bar/baz', 'blurfl/quux'], 1, 1);
0
 

Author Comment

by:cdc_sickle
Comment Utility
Please explain that, i do not understand it.
0
 
LVL 84

Expert Comment

by:ozo
Comment Utility
perldoc File::Path
          NAME
                 File::Path - create or remove a series of directories

          SYNOPSIS
                 use File::Path

                 mkpath(['/foo/bar/baz', 'blurfl/quux'], 1, 0711);

                 rmtree(['foo/bar/baz', 'blurfl/quux'], 1, 1);

          DESCRIPTION
                 The  mkpath  function  provides a convenient way to create
                 directories, even if your mkdir kernel call  won't  create
                 more  than one level of directory at a time.  mkpath takes
                 three arguments:

                     the name of the path to create, or a  reference  to  a
                     list of paths to create,

                     a  boolean  value,  which if TRUE will cause mkpath to
                     print the name of each  directory  as  it  is  created
                     (defaults to FALSE), and

                     the  numeric mode to use when creating the directories
                     (defaults to 0777)

                 It  returns  a  list   of   all   directories   (including
                 intermediates,  determined  using  the Unix `/' separator)
                 created.

                 Similarly, the rmtree function provides a  convenient  way
                 to  delete  a  subtree  from the directory structure, much
                 like  the  Unix  command  rm  -r.   rmtree   takes   three
                 arguments:

                     the root of the subtree to delete, or a reference to a
                     list of roots.  All of the files and directories below
                     each  root,  as  well as the roots themselves, will be
                     deleted.

                     a boolean value, which if TRUE will  cause  rmtree  to
                     print  a  message each time it examines a file, giving
                     the name of the  file,  and  indicating  whether  it's
                     using  rmdir  or  unlink  to  remove  it, or that it's
                     skipping it.  (defaults to FALSE)
                     a boolean value, which if TRUE will  cause  rmtree  to
                     skip  any files to which you do not have delete access
                     (if running under VMS) or  write  access  (if  running
                     under  another  OS).   This  will change in the future
                     when a criterion for  `delete  permission'  under  OSs
                     other than VMS is settled.  (defaults to FALSE)

                 It  returns  the  number  of  files  successfully deleted.
                 Symlinks are treated as ordinary files.

                 NOTE: If the  third  parameter  is  not  TRUE,  rmtree  is
                 unsecure  in  the  face of failure or interruption.  Files
                 and directories which were not deleted may  be  left  with
                 permissions  reset  to  allow world read and write access.
                 Note also that the occurrence of errors in rmtree  can  be
                 determined  only  by  trapping  diagnostic  messages using
                 $SIG{__WARN__}; it is not apparent from the return  value.
                 Therefore,  you  must  be  extremely  careful  about using
                 rmtree($foo,$bar,0 in  situations  where  security  is  an
                 issue.

          AUTHORS
                 Tim   Bunce   <Tim.Bunce@ig.co.uk>   and   Charles  Bailey
                 <bailey@genetics.upenn.edu>

          REVISION
                 Current $VERSION is 1.0401.


0
 

Author Comment

by:cdc_sickle
Comment Utility
so would it be:

rmtree(['usr/htdocs/usindex/folderdelete, '??'], 1, 1);

folder delete is the folder i want to delete with files in it too.
0
 
LVL 84

Expert Comment

by:ozo
Comment Utility
rmtree('/usr/htdocs/usindex/folderdelete', 1, 1);
0
 
LVL 16

Expert Comment

by:maneshr
Comment Utility
"What variable to i use to tell it which directory to delete?"

in order to find out whether of not to delete the directory you will have to first find out how many items (files, directories symbolic links ) are originally present in the  directory that you want to delete. then, as the deletion of files is going on, you will have to count the no of files that were deleted.

if these 2 counts are equal only then can you remove the directory.

Therefore first you will have to decide on the rules for removing the directory and look at the various scenarios.
0
 

Author Comment

by:cdc_sickle
Comment Utility
rmtree('/usr/htdocs/usindex/folderdelete', 1, 1);

This doesn't seem to do anything... I have it running in a sub, and the sub does run because it displayes some text... But i look back at the folder and it is still their. Keep in mind, the folder was originally created by a script, ("nobody") so i thought it could be deleted by a script.
0
 
LVL 16

Expert Comment

by:maneshr
Comment Utility
here is the updated code...

#!/usr/bin/perl

print qq{
Usage: $0 <directory1> <directory 2> ....
  - Removes ALL files in that directory
} if $#ARGV<0;

$DEBUG=0;
$starting_dir=`pwd`;
chomp($starting_dir);

foreach $dir (@ARGV){
  push @dir,$dir;

  while ($dirs=pop @dir){
    $whereami=`pwd`;
    chomp($whereami);
    chomp($dirs);
    chdir $dirs;
    print "CHANGING to $dirs\n";

    while (<*>) {
      next if ($_ eq ".");
      next if ($_ eq "..");
      if (-d $_) {  ##  This entry is a directory, ignore it!!
        next if (-l $_);
        print "\t Dir-> ",$_,"\n" if $DEBUG;
       #push @dir,$dirs."/".$_;
      } elsif (-l $_) { ##  This entry is a SYMBOLIC LINK file, ignore it!!
        next;
      } elsif (-f $_) { ##  This entry is a PLAIN file, pick it!!
        print "\t Deleting File-> ",$_,"\n" if $DEBUG;

        ##  Try and delete the file
        $count=unlink $_;
        if ($count){  ##  YESSS!! File was deleted
          print "$_ Deleted!!\n";
        }else{
          print "$_ NOT Deleted!!\n";

        }
      }
    }
    exit if $DEBUG;

    if (chdir $starting_dir){ ##  Changed to the proper dir
      if (rmdir $dirs){ ##  Directory was successfully removed !!
        print "$dirs Removed\n";
      }else{
        print "$dirs NOT Removed: $!\n";
      }
    }else{
      print "Could not change to $starting_dir $!\n";
    }
    chdir $whereami;
  }
}
0
 

Author Comment

by:cdc_sickle
Comment Utility
Ok, well how do i tell it the directory to delete... And why do you have two directories?
0
 
LVL 16

Expert Comment

by:maneshr
Comment Utility
(rmdir $dirs)

will delete the directory and also check if the delete was successfull.

the reason i am using 2 dirs is because i cannot be in a directory & delete it at the same time.
so before i start doing anything i store my current directory.
next i delete the files and then i change to the original directory and delete the other directory.

Hope that helps.
0
 

Author Comment

by:cdc_sickle
Comment Utility
You still did not tell me where to specify the directory to be deleted!
0
 
LVL 16

Expert Comment

by:maneshr
Comment Utility
you have to pass the directory that you want to delete as a parameter to this script.

in fact if you just run the script, it will give you a brief help message about its usage.

Eg.

my_delete.pl /tmp

in the above you want to delete a single directory
OR

my_delete.pl /directory1 /directory2 etc...


in the above you can delete multiple directories.

0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 

Author Comment

by:cdc_sickle
Comment Utility
yeah, well i want to put this in a sub in my current script right now. how would i pass in directories like that?
0
 
LVL 16

Expert Comment

by:maneshr
Comment Utility
change the code as follows


&rmtree("usr/htdocs/usindex/folderdelete");

sub  {
  ($which_dir)=@_;

  push(@list_of_dirs,$which_dir);
##print qq{
##                   Usage: $0 <directory1> <directory 2> ....
##                     - Removes ALL files in that directory
##                   } if $#ARGV<0;

  $DEBUG=0;
  $starting_dir=`pwd`;
  chomp($starting_dir);

  foreach $dir (@list_of_dirs){
    push @dir,$dir;
.......

}
0
 
LVL 5

Expert Comment

by:PC_User321
Comment Utility
Have you tried
   `/usr/bin/rm -R $Directory`

Obviously the script must have sufficient permissions.
0
 
LVL 5

Expert Comment

by:PC_User321
Comment Utility
>> This doesn't seem to do anything...
Sounds as if your delete script does not have sufficient permissions.

To check permissions, run the script below.  It should create directories and then delete them.  That should work without problems.  It proves that the deletion mechanism works.
Then split the file into a 'copy' part and and a 'delete' part.  Put the copy part into your 'nobody' script, and put the 'delete' part where you want to do the deletion.  Run 'nobody', then the delete script.
If the deletion works, then your problem is solved.
If the deletion does not work, then the problem must be permissions.


#! /usr/local/bin/perl -w
$BaseDir = "/u/sickle/tempDir";
$DirToCopy = "/u/sickle/perl";
$DirToDelete = "/u/sickle/tempDir/perl";
print "Copying $DirToCopy to $BaseDir ...\n";
`/usr/bin/cp -r $DirToCopy $BaseDir`;
print Directory after copy ...\n";
print `ls $DirToDelete`;
`/usr/bin/rm -R $DirToDelete`;
print Directory after delete ...\n";
print `ls $DirToDelete`;
0
 
LVL 5

Expert Comment

by:PC_User321
Comment Utility
(Change the paths to suit your system)
0
 

Author Comment

by:cdc_sickle
Comment Utility
madonna:/usr/home/usindex/www$ perl delete.cgi
Copying /usr/htdocs/www/usindex/States/Texas/Houston/Categories/Food_Restaurants
/Italian_Restaurants/Moderate/test to /usr/www/htdocs/usindex ...
Can't exec "/usr/bin/cp": No such file or directory at delete.cgi line 6.
Directory after copy ...
ls: /usr/htdocs/www/usindex/States/Texas/Houston/Categories/Food_Restaurants/Ita
lian_Restaurants/Moderate/test: No such file or directory
Can't exec "/usr/bin/rm": No such file or directory at delete.cgi line 9.
Directory after delete ...
ls: /usr/htdocs/www/usindex/States/Texas/Houston/Categories/Food_Restaurants/Ita
lian_Restaurants/Moderate/test: No such file or directory
0
 
LVL 3

Expert Comment

by:jyu_88
Comment Utility
add my RemoveDir Sub routine into your code,
then, call it when you are ready to purge a directory, supposed named '/home/maneshr/togoDir',
&RemoveDir("/home/maneshr/togoDir);

my RemoveDir sub shown above is just a simplfied version of  rmtree from File::Path pointed by Ozo.
0
 

Author Comment

by:cdc_sickle
Comment Utility
Hey jyu!!! It worked, well, it deleted all the files in the directory, but it didn't delete the folder... Wierd, if you can answer that, ill give you another 50 points. Otherwise ill just give you the 50.
0
 
LVL 3

Expert Comment

by:jyu_88
Comment Utility
darn me, I forgot to remove the rootDir itself, add a line right before 'return 0' in the sub RemoveDir definition.


foreach $ent(@dirEnt) {
                $ent = $rootDir."/".$ent;
                if ( -f $ent) { unlink $ent }
                if ( -d $ent) { &RemoveDir($ent) }
                }
                return 0
                }
}
# ha, remove the rootDir itself. <<<<<<<<<<<
unlink $rootDir;

return 0
}

That will do it.
0
 
LVL 3

Expert Comment

by:jyu_88
Comment Utility
oops, the new line should be:
rmdir $rootDir;

instead of
unlink $rootDir;
0
 

Author Comment

by:cdc_sickle
Comment Utility
do i need the return 0's?
0
 

Author Comment

by:cdc_sickle
Comment Utility
Adjusted points to 100
0
 

Author Comment

by:cdc_sickle
Comment Utility
Thanks man!
0
 
LVL 3

Expert Comment

by:jyu_88
Comment Utility
return 0 is to feed back status of the call to this sub routine (or function as in C, or method as in Java, C++). This way, the caller program can tell if the call is succesful or not, if not, then what error is encoutered can be distinguished by different error code you defined yourself.

To capture the status, in your main program,
$status = &RemoveDir("/home/dirToGo");
if ( 0 == $status ) {       print "OK: RemoveDir succesful\n"}
else { print "Warning: error trying to remove /home/dirToGo. Error code: $status\n"
# more action for different error status.
}


To make the return statement really useful, you'd add more error-check stuff into the sub definition.
0
 

Author Comment

by:cdc_sickle
Comment Utility
Well, i just put it in a cgi script, and returned some html code, and took out the return 0. So its fine.
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

On Microsoft Windows, if  when you click or type the name of a .pl file, you get an error "is not recognized as an internal or external command, operable program or batch file", then this means you do not have the .pl file extension associated with …
Email validation in proper way is  very important validation required in any web pages. This code is self explainable except that Regular Expression which I used for pattern matching. I originally published as a thread on my website : http://www…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

728 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

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now