I have a script (got it from somewhere here in StackOverflow, credits don't go to me!) to
delete a folder + its contents. However, it's not working for me. After deleting the folder a record from my DB should be erased and this happens just fine. However, the folder doesn't get deleted and neither its contents! This is my code:
<?php
$filepath = dirname(__FILE__);
$gemeented = preg_replace( '#^(.*)/(.*?)/(.*?)/(.*?)/(.*?)/(.*?)$#', "$2", $filepath );
$plaatsd = preg_replace( '#^(.*)/(.*?)/(.*?)/(.*?)/(.*?)/(.*?)$#', "$4", $filepath );
$hrubriekd = preg_replace( '#^(.*)/(.*?)/(.*?)/(.*?)/(.*?)/(.*?)$#', "$5", $filepath );
$bedrijfn = preg_replace( '#^(.*)/(.*?)/(.*?)/(.*?)/(.*?)/(.*?)$#', "$6", $filepath );
$filepath2 = "http://".$gemeented.".url.nl/".$plaatsd."/".$hrubriekd."/".$bedrijfn."/";
$filepath3 = "http://".$gemeented.".url.nl/".$plaatsd."/".$bedrijfn."/";
echo $filepath2;
function Delete($filepath2)
{
if (is_dir($filepath2) === true)
{
$files = array_diff(scandir($filepath2), array('.', '..'));
foreach ($files as $file)
{
Delete(realpath($filepath2) . '/' . $file);
}
return rmdir($filepath2);
}
else if (is_file($filepath2) === true)
{
return unlink($filepath2);
}
return false;
}
?>
To make sure my $filepath2 is correct I echoed it, the result is:
http://dongen.mydomain.nl/s-gravenmoer/aandrijvingenenbesturingen/bedrijfsnaam/
That's exactly the folder I want gone, however, it ain't happening! Folder has CHMOD 755.
EDIT:
Just using $filepath won't work either, echo-ing that gives me:
/vhosts/mydomain.nl/subdomains/dongen/httpdocs/s-gravenmoer/aandrijvingenenbesturingen/bedrijfsnaam
I wasn't able to get the above script working, but I managed to find another script which works for me! Just enter the relative path and that's it!
$dirname = "../".$bedrijfn."/";
delete_directory($dirname);
function delete_directory($dirname) {
if (is_dir($dirname))
$dir_handle = opendir($dirname);
if (!$dir_handle)
return false;
while($file = readdir($dir_handle)) {
if ($file != "." && $file != "..") {
if (!is_dir($dirname."/".$file))
unlink($dirname."/".$file);
else
delete_directory($dirname.'/'.$file);
}
}
closedir($dir_handle);
rmdir($dirname);
return true;
}
Hope it helps somebody out!
Sander
You can't use url to delete files, you should give unlink a filesystem path.
(Edit: the same goes for rmdir)
Related
I have the code bellow where I'm creating a new folder and copying some files from another folder, and it's working fine.
Now I need to go on each php file inside new folder and change the word "empty" by some word passed through $_POST["variable"].
Maybe by str_replace but I'm stuck in the logic.
Thanks in advance!
if (!file_exists("/home//public_html/new_conf_folder/"))
{
mkdir("/home//public_html/new_conf_folder/", 0755, true);
$source = "/home/public_html/conf_folder/";
$destination = "/home/public_html/new_conf_folder";
$directory = opendir($source);
while(($file = readdir($directory)) != false)
{
copy($source.'/' .$file, $destination.'/'.$file);
}
}
Try this code its working for me:
// file_process.php
$destination="./"; // Current Directory
if (file_exists($destination))
{
$directory = opendir($destination);
while(($file = readdir($directory)) != false)
{
//echo $file."<br/>";
$contents=file_get_contents($file);
$contents=str_replace("\"empty\"",$_POST['variable'],$contents);
//$contents=str_replace("\"empty\"",$_POST['variable'],$contents); // use this if the word with qouts
//echo $contents;
$bytes_written=file_put_contents($file,$contents);
if($bytes_written>0)echo "File [$file] has been successfully processed.";
else echo "Process Failed.";
}
}
I am calling my php function from some other website which delete a folder on my server in background.
This is a function which I am using to delete a folder.
public static function remove($dir)
{
if (is_dir($dir)) {
$diropen = opendir($dir);
while($d = readdir($diropen)) {
if ($d!= '.' && $d != '..') {
self::remove($dir . "/$d");
}
}
#rmdir($dir);
} elseif (is_file($dir)) {
#unlink($dir);
}
}
If I am having three files in folder then it deletes only two and unable to delete last file or unlink fails on last file.
If I am having two files then it deletes only one file.
I have checked writable permission using is_writable it is true for all files.
Can somebody please help me out. or how to debug this behavior as this function is getting called in background.
my directory was open in some other function , so I closedir my folder and then above function working fine.
<?php
function delete_directory($target) {
if (is_dir($target))
$dir_handle = opendir($target);
if (!$dir_handle)
return false;
while($file = readdir($dir_handle)) {
if ($file != "." && $file != "..") {
if (!is_dir($dirname."/".$file))
unlink($dirname."/".$file);
else
delete_directory($target.'/'.$file);
}
}
closedir($dir_handle);
rmdir($target);
return true;
}
?>
use closedir and you'll be fine.
For example I had a folder called `Temp' and I wanted to delete or flush all files from this folder using PHP. Could I do this?
$files = glob('path/to/temp/*'); // get all file names
foreach($files as $file){ // iterate files
if(is_file($file)) {
unlink($file); // delete file
}
}
If you want to remove 'hidden' files like .htaccess, you have to use
$files = glob('path/to/temp/{,.}*', GLOB_BRACE);
If you want to delete everything from folder (including subfolders) use this combination of array_map, unlink and glob:
array_map( 'unlink', array_filter((array) glob("path/to/temp/*") ) );
This call can also handle empty directories ( thanks for the tip, #mojuba!)
Here is a more modern approach using the Standard PHP Library (SPL).
$dir = "path/to/directory";
if(file_exists($dir)){
$di = new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS);
$ri = new RecursiveIteratorIterator($di, RecursiveIteratorIterator::CHILD_FIRST);
foreach ( $ri as $file ) {
$file->isDir() ? rmdir($file) : unlink($file);
}
}
foreach (new DirectoryIterator('/path/to/directory') as $fileInfo) {
if(!$fileInfo->isDot()) {
unlink($fileInfo->getPathname());
}
}
This code from http://php.net/unlink:
/**
* Delete a file or recursively delete a directory
*
* #param string $str Path to file or directory
*/
function recursiveDelete($str) {
if (is_file($str)) {
return #unlink($str);
}
elseif (is_dir($str)) {
$scan = glob(rtrim($str,'/').'/*');
foreach($scan as $index=>$path) {
recursiveDelete($path);
}
return #rmdir($str);
}
}
$dir = 'your/directory/';
foreach(glob($dir.'*.*') as $v){
unlink($v);
}
Assuming you have a folder with A LOT of files reading them all and then deleting in two steps is not that performing.
I believe the most performing way to delete files is to just use a system command.
For example on linux I use :
exec('rm -f '. $absolutePathToFolder .'*');
Or this if you want recursive deletion without the need to write a recursive function
exec('rm -f -r '. $absolutePathToFolder .'*');
the same exact commands exists for any OS supported by PHP.
Keep in mind this is a PERFORMING way of deleting files. $absolutePathToFolder MUST be checked and secured before running this code and permissions must be granted.
See readdir and unlink.
<?php
if ($handle = opendir('/path/to/files'))
{
echo "Directory handle: $handle\n";
echo "Files:\n";
while (false !== ($file = readdir($handle)))
{
if( is_file($file) )
{
unlink($file);
}
}
closedir($handle);
}
?>
The simple and best way to delete all files from a folder in PHP
$files = glob('my_folder/*'); //get all file names
foreach($files as $file){
if(is_file($file))
unlink($file); //delete file
}
Got this source code from here - http://www.codexworld.com/delete-all-files-from-folder-using-php/
unlinkr function recursively deletes all the folders and files in given path by making sure it doesn't delete the script itself.
function unlinkr($dir, $pattern = "*") {
// find all files and folders matching pattern
$files = glob($dir . "/$pattern");
//interate thorugh the files and folders
foreach($files as $file){
//if it is a directory then re-call unlinkr function to delete files inside this directory
if (is_dir($file) and !in_array($file, array('..', '.'))) {
echo "<p>opening directory $file </p>";
unlinkr($file, $pattern);
//remove the directory itself
echo "<p> deleting directory $file </p>";
rmdir($file);
} else if(is_file($file) and ($file != __FILE__)) {
// make sure you don't delete the current script
echo "<p>deleting file $file </p>";
unlink($file);
}
}
}
if you want to delete all files and folders where you place this script then call it as following
//get current working directory
$dir = getcwd();
unlinkr($dir);
if you want to just delete just php files then call it as following
unlinkr($dir, "*.php");
you can use any other path to delete the files as well
unlinkr("/home/user/temp");
This will delete all files in home/user/temp directory.
Another solution:
This Class delete all files, subdirectories and files in the sub directories.
class Your_Class_Name {
/**
* #see http://php.net/manual/de/function.array-map.php
* #see http://www.php.net/manual/en/function.rmdir.php
* #see http://www.php.net/manual/en/function.glob.php
* #see http://php.net/manual/de/function.unlink.php
* #param string $path
*/
public function delete($path) {
if (is_dir($path)) {
array_map(function($value) {
$this->delete($value);
rmdir($value);
},glob($path . '/*', GLOB_ONLYDIR));
array_map('unlink', glob($path."/*"));
}
}
}
Posted a general purpose file and folder handling class for copy, move, delete, calculate size, etc., that can handle a single file or a set of folders.
https://gist.github.com/4689551
To use:
To copy (or move) a single file or a set of folders/files:
$files = new Files();
$results = $files->copyOrMove('source/folder/optional-file', 'target/path', 'target-file-name-for-single-file.only', 'copy');
Delete a single file or all files and folders in a path:
$files = new Files();
$results = $files->delete('source/folder/optional-file.name');
Calculate the size of a single file or a set of files in a set of folders:
$files = new Files();
$results = $files->calculateSize('source/folder/optional-file.name');
<?
//delete all files from folder & sub folders
function listFolderFiles($dir)
{
$ffs = scandir($dir);
echo '<ol>';
foreach ($ffs as $ff) {
if ($ff != '.' && $ff != '..') {
if (file_exists("$dir/$ff")) {
unlink("$dir/$ff");
}
echo '<li>' . $ff;
if (is_dir($dir . '/' . $ff)) {
listFolderFiles($dir . '/' . $ff);
}
echo '</li>';
}
}
echo '</ol>';
}
$arr = array(
"folder1",
"folder2"
);
for ($x = 0; $x < count($arr); $x++) {
$mm = $arr[$x];
listFolderFiles($mm);
}
//end
?>
For me, the solution with readdir was best and worked like a charm. With glob, the function was failing with some scenarios.
// Remove a directory recursively
function removeDirectory($dirPath) {
if (! is_dir($dirPath)) {
return false;
}
if (substr($dirPath, strlen($dirPath) - 1, 1) != '/') {
$dirPath .= '/';
}
if ($handle = opendir($dirPath)) {
while (false !== ($sub = readdir($handle))) {
if ($sub != "." && $sub != ".." && $sub != "Thumb.db") {
$file = $dirPath . $sub;
if (is_dir($file)) {
removeDirectory($file);
} else {
unlink($file);
}
}
}
closedir($handle);
}
rmdir($dirPath);
}
public static function recursiveDelete($dir)
{
foreach (new \DirectoryIterator($dir) as $fileInfo) {
if (!$fileInfo->isDot()) {
if ($fileInfo->isDir()) {
recursiveDelete($fileInfo->getPathname());
} else {
unlink($fileInfo->getPathname());
}
}
}
rmdir($dir);
}
I've built a really simple package called "Pusheh". Using it, you can clear a directory or remove a directory completely (Github link). It's available on Packagist, also.
For instance, if you want to clear Temp directory, you can do:
Pusheh::clearDir("Temp");
// Or you can remove the directory completely
Pusheh::removeDirRecursively("Temp");
If you're interested, see the wiki.
I updated the answer of #Stichoza to remove files through subfolders.
function glob_recursive($pattern, $flags = 0) {
$fileList = glob($pattern, $flags);
foreach (glob(dirname($pattern).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir) {
$subPattern = $dir.'/'.basename($pattern);
$subFileList = glob_recursive($subPattern, $flags);
$fileList = array_merge($fileList, $subFileList);
}
return $fileList;
}
function glob_recursive_unlink($pattern, $flags = 0) {
array_map('unlink', glob_recursive($pattern, $flags));
}
This is a simple way and good solution. try this code.
array_map('unlink', array_filter((array) array_merge(glob("folder_name/*"))));
I wrote a basic content-management system for my website, including an administration panel. I understand basic file IO as well as copying via PHP, but my attempts at a backup script callable from the script have failed. I tried doing this:
//... authentication, other functions
for(scandir($homedir) as $buffer){
if(is_dir($buffer)){
//Add $buffer to an array
}
else{
//Back up the file
}
}
for($founddirectories as $dir){
for(scandir($dir) as $b){
//Backup as above, adding to $founddirectories
}
}
But it did not seem to work.
I know that I can do this using FTP, but I want a completely server-side solution that can be accessed anywhere with sufficient authorization.
Here is an alternative though: why don't you Zip the source directory instead?
function Zip($source, $destination)
{
if (extension_loaded('zip') === true)
{
if (file_exists($source) === true)
{
$zip = new ZipArchive();
if ($zip->open($destination, ZIPARCHIVE::CREATE) === true)
{
$source = realpath($source);
if (is_dir($source) === true)
{
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);
foreach ($files as $file)
{
$file = realpath($file);
if (is_dir($file) === true)
{
$zip->addEmptyDir(str_replace($source . '/', '', $file . '/'));
}
else if (is_file($file) === true)
{
$zip->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
}
}
}
else if (is_file($source) === true)
{
$zip->addFromString(basename($source), file_get_contents($source));
}
}
return $zip->close();
}
}
return false;
}
You can even unzip it afterwards and archive the same effect, although I must say I prefer having my backups compressed in zip file format.
if you have access to execute tar binary file through exec function it would be faster and better i think:
exec('tar -zcvf ' . realpath('some directory') .'/*);
or
chdir('some directory')
exec('tar -zcvf ./*');
You can use recursion.
for(scandir($dir) as $dir_contents){
if(is_dir($dir_contents)){
backup($dir_contents);
}else{
//back up the file
}
}
you got it almost right
$dirs = array($homedir);
$files = array();
while(count($dirs)) {
$dir = array_shift($dirs);
foreach(glob("$dir/*") as $e)
if(is_dir($e))
$dirs[] = $e;
else
$files[] = $e;
}
// here $files[] contains all files from $homedir and below
glob() is better than scandir() because of more consistent output
I us something called UPHP. Just call zip() to do that. here:
<?php
include "uphplib.php";
$folder = "data";
$dest = "backup/backup.zip";
zip($folder, $dest);
?>
UPHP is a PHP library. download: here
Here is a backup script with ftp, scp, mysqldump, pg_dump and filesystem capabilities https://github.com/skywebro/php-backup
i use a simple function to backup a file:
<?php
$oldfile = 'myfile.php';
$newfile = 'backuped.php';
copy($oldfile, $newfile) or die("Unable to backup");
echo 'Backup is Completed';
?>
when moving one file from one location to another i use
rename('path/filename', 'newpath/filename');
how do you move all files in a folder to another folder? tried this one without result:
rename('path/*', 'newpath/*');
A slightly verbose solution:
// Get array of all source files
$files = scandir("source");
// Identify directories
$source = "source/";
$destination = "destination/";
// Cycle through all source files
foreach ($files as $file) {
if (in_array($file, array(".",".."))) continue;
// If we copied this successfully, mark it for deletion
if (copy($source.$file, $destination.$file)) {
$delete[] = $source.$file;
}
}
// Delete all successfully-copied files
foreach ($delete as $file) {
unlink($file);
}
Please try this solution, it's tested successfully ::
<?php
$files = scandir("f1");
$oldfolder = "f1/";
$newfolder = "f2/";
foreach($files as $fname) {
if($fname != '.' && $fname != '..') {
rename($oldfolder.$fname, $newfolder.$fname);
}
}
?>
An alternate using rename() and with some error checking:
$srcDir = 'dir1';
$destDir = 'dir2';
if (file_exists($destDir)) {
if (is_dir($destDir)) {
if (is_writable($destDir)) {
if ($handle = opendir($srcDir)) {
while (false !== ($file = readdir($handle))) {
if (is_file($srcDir . '/' . $file)) {
rename($srcDir . '/' . $file, $destDir . '/' . $file);
}
}
closedir($handle);
} else {
echo "$srcDir could not be opened.\n";
}
} else {
echo "$destDir is not writable!\n";
}
} else {
echo "$destDir is not a directory!\n";
}
} else {
echo "$destDir does not exist\n";
}
tried this one?:
<?php
$oldfolderpath = "old/folder";
$newfolderpath = "new/folder";
rename($oldfolderpath,$newfolderpath);
?>
So I tried to use the rename() function as described and I kept getting the error back that there was no such file or directory. I placed the code within an if else statement in order to ensure that I really did have the directories created. It looked like this:
$tempDir = '/home/site/images/tmp/';
$permanentDir = '/home/site/images/' . $claimid; // this was stored above
mkdir($permanentDir,0775);
if(is_dir($permanentDir)){
echo $permanentDir . ' is a directory';
if(is_dir($tempDir)){
echo $tempDir . ' is a directory';
}else{
echo $tempDir . ' is not a directory';
}
}else{
echo $permanentDir . ' is not a directory';
}
rename($tempDir . "*", $permanentDir);
So when I ran the code again, it spit out that both paths were directories. I was stumped. I talked with a coworker and he suggested, "Why not just rename the temp directory to the new directory, since you want to move all the files anyway?"
Turns out, this is what I ended up doing. I gave up trying to use the wildcard with the rename() function and instead just use the rename() to rename the temp directory to the permanent one.
so it looks like this.
$tempDir = '/home/site/images/tmp/';
$permanentDir = '/home/site/images/' . $claimid; // this was stored above
mkdir($permanentDir,0775);
rename($tempDir, $permanentDir);
This worked beautifully for my purposes since I don't need the old tmp directory to remain there after the files have been uploaded and "moved".
Hope this helps. If anyone knows why the wildcard doesn't work in the rename() function and why I was getting the error stating above, please, let me know.
Move or copy the way I use it
function copyfiles($source_folder, $target_folder, $move=false) {
$source_folder=trim($source_folder, '/').'/';
$target_folder=trim($target_folder, '/').'/';
$files = scandir($source_folder);
foreach($files as $file) {
if($file != '.' && $file != '..') {
if ($move) {
rename($source_folder.$file, $target_folder.$file);
} else {
copy($source_folder.$file, $target_folder.$file);
}
}
}
}
function movefiles($source_folder, $target_folder) {
copyfiles($source_folder, $target_folder, $move=true);
}
try this:
rename('path/*', 'newpath/');
I do not see a point in having an asterisk in the destination
If the target directory doesn't exist, you'll need to create it first:
mkdir('newpath');
rename('path/*', 'newpath/');
As a side note; when you copy files to another folder, their last changed time becomes current timestamp. So you should touch() the new files.
... (some codes for directory looping) ...
if (copy($source.$file, $destination.$file)) {
$delete[] = $source.$file;
$filetimestamp = filemtime($source.$file);
touch($destination.$file,$filetimestamp);
}
... (some codes) ...
Not sure if this helps anyone or not, but thought I'd post anyway. Had a challenge where I has heaps of movies I'd purchased and downloaded through various online stores all stored in one folder, but all in their own subfolders and all with different naming conventions. I wanted to move all of them into the parent folder and rename them all to look pretty. all of the subfolders I'd managed to rename with a bulk renaming tool and conditional name formatting. the subfolders had other files in them i didn't want. so i wrote the following php script to, 1. rename/move all files with extension mp4 to their parent directory while giving them the same name as their containing folder, 2. delete contents of subfolders and look for directories inside them to empty and then rmdir, 3. rmdir the subfolders.
$handle = opendir("D:/Movies/");
while ($file = readdir($handle)) {
if ($file != "." && $file != ".." && is_dir($file)) {
$newhandle = opendir("D:/Movies/".$file);
while($newfile = readdir($newhandle)) {
if ($newfile != "." && $newfile != ".." && is_file("D:/Movies/".$file."/".$newfile)) {
$parts = explode(".",$newfile);
if (end($parts) == "mp4") {
if (!file_exists("D:/Movies/".$file.".mp4")) {
rename("D:/Movies/".$file."/".$newfile,"D:/Movies/".$file.".mp4");
}
else {
unlink("D:/Movies/".$file."/".$newfile);
}
}
else { unlink("D:/Movies/".$file."/".$newfile); }
}
else if ($newfile != "." && $newfile != ".." && is_dir("D:/Movies/".$file."/".$newfile)) {
$dirhandle = opendir("D:/Movies/".$file."/".$newfile);
while ($dirfile = readdir($dirhandle)){
if ($dirfile != "." && $dirfile != ".."){
unlink("D:/Movies/".$file."/".$newfile."/".$dirfile);
}
}
rmdir("D:/Movies/".$file."/".$newfile);
}
}
unlink("D:/Movies/".$file);
}
}
i move all my .json files from root folder to json folder with this
foreach (glob("*.json") as $filename) {
rename($filename,"json/".$filename);
}
pd: someone 2020?