Question

I am working on a prototype of an online storage with PHP and I got this problem. I call the delete_file() function from the client, the function checks if the item to be deleted is a file or a directory and deletes it accordingly. If the item is a directory then it will call another function that will delete all its' contents and the directory itself.

function delete_file (){
    global $directory;
    $rec_data = trim($_POST['selected']);
    $selected_items = explode(";", $rec_data);

    if (count($selected_items) < 1){
        echo "0";
    }
    else {
        foreach ($selected_items as $item){
            if (is_dir("{$directory}/{$item}")){
                recursiveRemoveDirectory("{$directory}/{$item}");
            }
            else {
                unlink("{$directory}/{$item}");
            }
        }
        echo "1";
    }
}

function recursiveRemoveDirectory($rm_directory){
    foreach(scandir($rm_directory) as $file){
        if($file != "." && $file != ".."){
            if(is_dir($file)) {
                recursiveRemoveDirectory($file);
            }
            else {
                unlink($file);
            }
        }
    }
    rmdir($rm_directory);
}

Problem: It works but, this also deletes the parent directory .e.g data > username > dir, if I want to delete dir, it will also delete username. I've tried with various other methods with no success.

Was it helpful?

Solution 3

I tried both answers, they did solve a problem I had with the code but it did not solve the issue I was having in which the parent directory was being deleted along with the selected items.

After looking and changing the code for some time I finally realized that the problem wasn't in the recursiveDeleteDirectory() function but in the delete_file() function itself.

The $selected_itemsvariable gets a concatenated string of the names of the items to be selected, it trims any unnecessary whitespaces and makes an array from the string. The problem was that somehow $selected_items got an additional empty entry which meant that I was then executing recursiveRemoveDirectory("{$directory}/"); instead of recursiveRemoveDirectory("{$directory}/{$item}");.

I solved all this by adding:

if (empty($item)){
    continue;
}

Here is how the code looks like:

function delete_file (){
    global $directory;
    $selected_items = explode(";", trim($_POST['selected']));

    if (count($selected_items) < 1){
        echo "0";
    }
    else {
        foreach ($selected_items as $item){
            if (empty($item)){
                continue;
            }
            if (is_dir("{$directory}/{$item}")){
                recursiveRemoveDirectory("{$directory}/{$item}");
            }
            else if (is_file("{$directory}/{$item}")){
                unlink("{$directory}/{$item}");
            }
        }
        echo "1";
    }

}

function recursiveRemoveDirectory($rm_directory){
    $files = file_explore();
    if(count($files) > 0){
        foreach($files as $file){
            if(is_dir("{$rm_directory}/{$file}")) {
                recursiveRemoveDirectory("{$rm_directory}/{$file}");
            }
            else if (is_file("{$rm_directory}/{$file}")) {
                unlink("{$rm_directory}/{$file}");
            }
        }
    }
    rmdir($rm_directory);

Now my problem, which isn't really a stack overflow problem is the naming conversions of php functions, I never used underscore on function names but recently that have changed and I feel that's a bad habit, if someone wants to comment about that, you are free to do so, I really want to know how things must be done in php.

Cheers!

OTHER TIPS

function recursiveRemoveDirectory($rm_directory){
    foreach(scandir($rm_directory) as $file){
        if($file != "." && $file != ".."){
            if(is_dir($file)) {                  <--- error starts here!
                recursiveRemoveDirectory($file);
            }
            else {
                unlink($file);                   <--- error ends here!
            }
        }
    }
    rmdir($rm_directory);
}

Replace the marked lines with

            if(is_dir("$rm_directory/$file")) {
                recursiveRemoveDirectory("$rm_directory/$file");
            else {
                unlink("$rm_directory/$file");
            }

You got that right in your delete_file function, but missed it in the recursive one.

Try this:

function recursiveRemoveDirectory($dir) {
    foreach(scandir($dir) as $file) {
        if ('.' === $file || '..' === $file) continue;
        if (is_dir("$dir/$file")) recursiveRemoveDirectory("$dir/$file");
        else unlink("$dir/$file");
    }
    rmdir($dir);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top