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.
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);
}
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!
Related
I have a directory on my server that I need to clear out using PHP. I need to delete all files and folders inside this directory, however, I do not want to delete the main directory itself. Everything I have read, examples I have found, they all seem to delete everything inside the directory given but then after it also deletes the given directory. One function I tried is below, but again it also deletes the main directory and I can't have that.
<?php
function rrmdir($dir) {
if (is_dir($dir)) {
$objects = scandir($dir);
foreach ($objects as $object) {
if ($object != "." && $object != "..") {
if (filetype($dir."/".$object) == "dir")
rrmdir($dir."/".$object);
else unlink ($dir."/".$object);
}
}
reset($objects);
rmdir($dir);
}
}
?>
Get rid of this rmdir($dir); on the last part of your function.
function rrmdir($dir) {
if (is_dir($dir)) {
$objects = scandir($dir);
foreach ($objects as $object) {
if ($object != "." && $object != "..") {
if (filetype($dir."/".$object) == "dir")
rrmdir($dir."/".$object);
else unlink ($dir."/".$object);
}
}
reset($objects);
// rmdir($dir); => this line deletes the directory you specified after its content has been deleted
}
}
Remove this line from your existing code rmdir($dir);, with this line your are also removing the parent directory that you passed on your function parameter. I've also added what code snippet I usually use for deleting contents from directory.
function remove_directory($str) {
//It it's a file.
if (is_file($str)) {
//Attempt to delete it.
return unlink($str);
}
//If it's a directory.
elseif (is_dir($str)) {
//Get a list of the files in this directory.
$scan = glob(rtrim($str,'/').'/*');
//Loop through the list of files.
foreach($scan as $index=>$path) {
//Call our recursive function.
remove_directory($path);
}
//Remove the directory itself.
return #rmdir($str);
}
}
//call our function
$dir='directory_name';
remove_directory($dir);
The version of the code I posted before also deleted subdirectories, so removing the last rmdir in the code would stop it from doing that. However, I was able to make changes to the code that works. This code will delete all contents inside the given directory including files and folders without deleting the given directory.
function rrmdir($dir, $issub = false) {
if (is_dir($dir)) {
$objects = scandir($dir);
foreach ($objects as $object) {
if ($object != "." && $object != "..") {
if (filetype($dir."/".$object) == "dir")
rrmdir($dir."/".$object, true);
else unlink ($dir."/".$object);
}
}
reset($objects);
if($issub) {
rmdir($dir);
}
}
}
How do i delete all files and directories in folder one. Below is my folder structure:
Delete.php
<?php
function rrmdir($dir) {
$dir = 'C:xampp/htdocs/project/user/one';
if (is_dir($dir)) {
$objects = scandir($dir);
foreach ($objects as $object) {
if ($object != "." && $object != "..") {
if (is_dir($dir."/".$object)){
rrmdir($dir."/".$object);
}
else{
unlink($dir."/".$object);
}
}
}
rmdir($dir);
}
}
?>
I have tried the code that i get from here but the code did not do anything. As if the function is not working.
This will delete your files recursively. It will work fine, and make sure to have a backup of your files, before getting it deleted.
Here we are using glob function to delete files recursively.
<?php
ini_set('display_errors', 1);
function delete($filePath,$array=array())
{
if(is_array($array) && count($array)>0)
{
foreach($array as $filePath)
{
if(is_dir($filePath))
{
delete(glob($filePath."/*"));//first calling function itself to remove files first.
rmdir($filePath);//removing directory at the end.
}
else
{
unlink($filePath);//unlinking a file.
}
}
}
}
print_r(delete(glob("C:xampp/htdocs/project/user/one/*")));
What's the fastest way to delete all files in all sub-folders except those whose filename is 'whatever.jpg' in PHP?
Why not use iterators? This is tested:
function run($baseDir, $notThis)
{
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($baseDir), RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
if ($file->isFile() && $file->getFilename() != $notThis) {
#unlink($file->getPathname());
}
}
}
run('/my/path/base', 'do_not_cancel_this_file.jpg');
This should be what youre looking for, $but is an array holding exceptions.
Not sure if its the fastest, but its the most common way for directory iteration.
function rm_rf_but ($what, $but)
{
if (!is_dir($what) && !in_array($what,$but))
#unlink($what);
else
{
if ($dh = opendir($what))
{
while(($item = readdir($dh)) !== false)
{
if (in_array($item, array_merge(array('.', '..'),$but)))
continue;
rm_rf_but($what.'/'.$item, $but);
}
}
#rmdir($what); // remove this if you dont want to delete the directory
}
}
Example use:
rm_rf_but('.', array('notme.jpg','imstayin.png'));
Untested:
function run($baseDir) {
$files = scandir("{$baseDir}/");
foreach($files as $file) {
$path = "{$badeDir}/{$file}";
if($file != '.' && $file != '..') {
if(is_dir($path)) {
run($path);
} elseif(is_file($path)) {
if(/* here goes you filtermagic */) {
unlink($path);
}
}
}
}
}
run('.');
I use this custom, simple script I made, somehow it's failing but it always returns true.
This class unlink the files that are placed in an array which goes through them then increments the counter on success of a file that was deleted, this is my script:
<?php
class Delete
{
function deleteFiles($array)
{
if(is_array($array))
{
$filecount = count($array);
$count = 0;
foreach($array as $file)
{
if(file_exists($file))
{
$remove = unlink($file);
if($remove)
{
$count++;
}
}
else
{
return false;
}
}
if($count == $filecount)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
}
?>
Basically I need improvements on how to make it foolproof so that the images in the array are completely deleted not returning true once an unlink has deleted the file when it hasn't, so I have no idea why it's not actually deleting the files properly.
Sometimes it works perfectly.
change if($remove) to if($remove && !file_exists($file))
Also, be aware that sometimes an unlink will fail on Windows: http://ie.php.net/manual/en/function.unlink.php#100580
you could add a call to is_file() after the unlink to check if the file is still there
Hi I am looking for help to write a short script which will locate all files in a folder (which has sub-folders) list the path and filename in two seperate values before submitting to a database.
Can anyone help?
i have a recursive function to delete a folder, you'd have to change it so instead of calling the ´unlink´ function you could save it in a variable or in a database..
public function deleteFolder($dirname) {
if (is_dir($dirname)){
$dir_handle = opendir($dirname);
}
if (!isset($dir_handle) || !$dir_handle){
return false;
}
while($file = readdir($dir_handle)) {
if ($file != "." && $file != "..") {
if (!is_dir($dirname."/".$file)){
//change this line
unlink($dirname."/".$file);
} else {
//recursive call
$this->deleteFolder($dirname.'/'.$file);
}
}
}
closedir($dir_handle);
//also change this one
rmdir($dirname);
return true;
}
hope this helps.. good luck!
<?php
print_r(getPathFiles("./"));
function getPathFiles($dir) {
$ite=new RecursiveDirectoryIterator($dir);
$foo=new RecursiveIteratorIterator($ite);
$ret=array();
foreach ($foo as $path=>$cur) {
$ret[]=array('dir'=>dirname($path),'file'=>basename($path));
}
return $ret;
}
?>