32

I am using this peice of code:

$target = 'extracted/' . $name[0];  
$scan = scandir($target);

To scan the directory of a folder which is used for zip uploads. I want to be able to find all the folders inside my $target folder so I can delete them and their contents, leaving only the files in the $target directory.

Once I have returned the contents of the folder, I don't know how to differentiate between the folders and the files to be able to delete the folders.

Also, I have been told that the rmdir() function can't delete folders which have content inside them, is there any way around this?

Thanks, Ben.

JYelton
  • 35,664
  • 27
  • 132
  • 191
Ben McRae
  • 3,551
  • 13
  • 36
  • 31

9 Answers9

61

To determine whether or not you have a folder or file use the functions is_dir() and is_file()

For example:

$path = 'extracted/' . $name[0];
$results = scandir($path);

foreach ($results as $result) {
    if ($result === '.' or $result === '..') continue;

    if (is_dir($path . '/' . $result)) {
        //code to use if directory
    }
}
JYelton
  • 35,664
  • 27
  • 132
  • 191
travis-146
  • 1,075
  • 1
  • 10
  • 20
  • 2
    This is brilliant, works perfectly! Unfotunatly i dont understand what this part does 'if ($result === '.' or $result === '..') continue;', would you mind explaining please. Thanks again. – Ben McRae Mar 04 '09 at 00:27
  • 3
    @Ben McRae: This is because scandir returns the results "." and ".." as part of the array, and in most cases you want to ignore those results, which is why I included that as part of the foreach – travis-146 Mar 04 '09 at 23:08
  • Just to add some piece of additional information: "." represents the current directory, while ".." represents the folder's parent directory. – shock_gone_wild Oct 08 '15 at 07:56
36

Better to use DirectoryIterator

$path = 'extracted'; // '.' for current
foreach (new DirectoryIterator($path) as $file) {
    if ($file->isDot()) continue;

    if ($file->isDir()) {
        print $file->getFilename() . '<br />';
    }
}
Dominic
  • 62,658
  • 20
  • 139
  • 163
3

First off, rmdir() cannot delete a folder with contents. If safe mode is disabled you can use the following.

exec("rm -rf folder/"); 

Also look at is_dir()/is_file() or even better the PHP SPL.

Hawk Kroeger
  • 2,336
  • 17
  • 21
  • your remove function worked a treat! what does rm -rf actually do? thanks – Ben McRae Mar 04 '09 at 00:42
  • For anyone wondering, `rm -rf` runs the `rm` function on the target directory (folder/ in this case) with the options `-r` (recursive - recursively remove files and folders inside the target folder) and `-f` (force - don't prompt with errors etc. and ignore nonexistent files). Basically, it makes sure that all files and folders inside your target folder are dealt with when removing the target. In general if you try `rm` on a folder which contains other stuff, it'll just throw an error saying it's not empty. [more details here](http://www.tutorialspoint.com/unix_commands/rm.htm) – andyface Mar 11 '14 at 12:57
2
$directories = scandir('images');
foreach($directories as $directory){
    if($directory=='.' or $directory=='..' ){
        echo 'dot';
    }else{
            if(is_dir($directory)){
                  echo $directory .'<br />';
            }
    }
} 

a simpler and perhaps faster version

Steel Brain
  • 4,321
  • 28
  • 38
alex
  • 21
  • 1
1

scandir will scan the entire directory, you can manually filter.

but if you are lazy like I am, then use glob

$scan = glob($target."/*",GLOB_ONLYDIR);

and it will output an array of all your directories of your target.

1

To get all the files in all the sub, sub folders

function myfunction($dir){

foreach ($dir as $dirname => $file) {

if(is_dir($file) &&  $file != '.' &&  $file != '..' ) { 

     // echo $file;
      $newDir = scandir($file);
      myfunction($newDir);

    }elseif($file !='.' && $file != '..'){

        echo "<br>File name is ---";
        echo  $file;
    }

} // end foreach


}  //function ends 

$dirpass = scandir($mypath3); // set directory
echo myfunction($dirpass); //     pass directory

We will get the result like below (plz ignore file names )

File name is ----->index.PHP
File name is -----> 100000045   Invoices   Sales   Magento Admin.png
File name is -----> 100000142   Orders   Sales   Magento Admin(1).png
File name is -----> 100000142   Orders   Sales   Magento Admin.png
File name is ----->hrc-siberian-tiger-2-jpg_21253111.jpg
File name is ----->images (3rd copy).jpeg
File name is ----->images (4th copy).jpeg
File name is ----->images (5th copy).jpeg
File name is ----->images (another copy).jpeg
File name is ----->images (copy).jpeg
File name is ----->images.jpeg
File name is ----->JPEG_example_JPG_RIP_100.jpg
File name is ----->preload
File name is ----->Stonehenge (3rd copy).jpg
File name is ----->Stonehenge (4th copy).jpg
File name is ----->Stonehenge (5th copy).jpg
File name is ----->Stonehenge (another copy).jpg
File name is ----->Stonehenge (copy).jpg
File name is ----->Stonehenge.jpg
inrsaurabh
  • 602
  • 1
  • 8
  • 17
0

You also wanted to remove items if they were inside that directory. rmdir does not allow you to remove directories containing files. But there is a simple sollution.

array_map('unlink', glob($target.'/*/*'));
array_map('rmdir',glob($target."/*",GLOB_ONLYDIR));

First it will unlink all the files in all sub-directories.
Secondly it will remove all directories, because they contain no files.

If you got sub-sub-directories, then you should add another 2 lines like this:

array_map('unlink', glob($target.'/*/*/*')); //remove sub-sub-files
array_map('rmdir',glob($target."/*/*",GLOB_ONLYDIR)); //remove sub-sub-directories

array_map('unlink', glob($target.'/*/*')); //remove sub-files
array_map('rmdir',glob($target."/*",GLOB_ONLYDIR)); //remove sub-directories
0

The quick and dirty way:

$folders = glob("<path>/*", GLOB_ONLYDIR);

A more versatile and object-oriented solution, inspired by earlier answers using DirectoryIterator but slightly more concise and general purpose:

    $path = '<path>';
    $folders = [];

    foreach (new \DirectoryIterator($path) as $file)
    {
        if (!$file->isDot() && $file->isDir())
        {
            $folders[] = $file;
        }
    }
Andreas Bergström
  • 13,891
  • 5
  • 59
  • 53
0

here is one function i used mostly to parse archives and directories

function scan_full_dir($dir,$child=false){
    $dir_content_list = scandir($dir);
    foreach($dir_content_list as $value) 
    { 
        if($value === '.' || $value === '..') {continue;} 
        // check if we have file 
         if(is_file($dir.'/'.$value)) {
            echo '<br> File Name --> '.$value;
            continue; 
         }
        // check if we have directory
        if (is_dir($dir.'/'.$value)) {
            if(!$child){ 
                echo '<br> parent --> '.$value;
            }else{
                echo '<br> child of '.$child.' --> '.$value;    
            }
            scan_full_dir($dir.'/'.$value,$value);
        }       
    }   
}

output sample

parent --> fonts
File Name --> standard
parent --> steps
child of steps --> pcb
File Name --> .attrlist.sum
File Name --> .profile.sum
File Name --> .stephdr.sum
File Name --> attrlist
child of pcb --> netlists
child of netlists --> cadnet
File Name --> .netlist.sum
File Name --> netlist
File Name --> profile
File Name --> stephdr

// to scan dir

scan_full_dir('path/of/myfolder');

// to scan archive without opening it , supported formats : gz, zip, tar and bz files.

scan_full_dir('phar://uploads/youarchive.zip);
user889030
  • 4,353
  • 3
  • 48
  • 51