Deleting Directory Contents & SubDirectory Contents - php

I've set up some PHP to delete a directory, it's contents, and any subdirectory and its contents... I'm new to PHP so I'm most definitely doing something WRONG or am doing something in the most inefficient way.
Looking for some references or suggestion on how to do this better...
By the way, this code works fine. Using PHP 5.3.8.
chmod($main_dir, 0755);
if ($handle = opendir($main_dir)) {
while (false !== ($entry = readdir($handle))) {
$absolute_path = $main_dir.'/'.$entry;
if ($entry != "." && $entry != "..") {
chmod($absolute_path, 0755);
unlink($absolute_path);
//check if any folders exist, then delete files within
if (file_exists($absolute_path) && is_dir($absolute_path)) {
if ($child_handle = opendir($absolute_path)) {
while (false !== ($child_entry = readdir($child_handle))) {
$child_absolute_path = $absolute_path.'/'.$child_entry;
if ($child_entry != "." && $child_entry != "..") {
chmod($child_absolute_path, 0755);
unlink($child_absolute_path);
}
}
closedir($child_handle);
}
}
rmdir($absolute_path);
}
}
closedir($handle);
}
rmdir($main_dir);
Any thoughts? Much appreciated!
Im using PHP 5.3.8

You can use RecursiveDirectoryIterator to list all files and folders then delete them. Please Note that you have to use RecursiveIteratorIterator::CHILD_FIRST so that the files are deleted before the folder.
$dir = __DIR__ . "/test";
$di = new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS);
$ri = new RecursiveIteratorIterator($di, RecursiveIteratorIterator::CHILD_FIRST);
foreach ( $ri as $file ) {
$file->isDir() ? rmdir($file) : unlink($file);
}

Related

How to delete file in PHP

I want to delete files in a specific directory in PHP. How can I achieve this?
I have the following code but it does not delete the files.
$files = array();
$dir = dir('files');
while ($file = $dir->read()) {
if ($file != '.' && $file != '..') {
$files[] = $file;
}
unlink($file);
}
I think your question isn't specific, this code must clear all files in the directory 'files'.
But there are some errors in that code I think, and here is the right code:
$files= array();
$dir = dir('files');
while (($file = $dir->read()) !== false) { // You must supply a condition to avoid infinite looping
if ($file != '.' && $file != '..') {
$files[] = $file; // In this array you push the valid files in the provided directory, which are not (. , ..)
}
unlink('files/'.$file); // This must remove the file in the queue
}
And finally make sure that you provided the right path to dir().
You can get all directory contents with glob and check if the value is a file with is_file() before unlinking it.
$files = glob('files/*'); // get directory contents
foreach ($files as $file) { // iterate files
// Check if file
if (is_file($file)) {
unlink($file); // delete file
}
}
If you want to remove files matching a pattern like .png or .jpg, you have to use
$files = glob('/tmp/*.{png,jpg}', GLOB_BRACE);
See manual for glob.

Creating a ZIP backup file - No errors thrown, but the ZIP file is not showing up

$path = '/home/username/www/;
if($zip = new ZipArchive){
if($zip->open('backup_'. time() .'.zip', ZipArchive::CREATE)){
if(false !== ($dir = opendir($path))){
while (false !== ($file = readdir($dir))){
if ($file != '.' && $file != '..' && $file != 'aaa'){
$zip->addFile($path . $file);
echo 'Adding '. $file .' to path '. $path . $file .' <br>';
}
}
}
else
{
echo 'Can not read dir';
}
$zip->close();
}
else
{
echo 'Could not create backup file';
}
}
else
{
echo 'Could not launch the ZIP libary. Did you install it?';
}
Hello again Stackoverflow! I want to backup a folder with all its content including (empty) subfolders and every file in them, whilst excluding a single folder (and ofcourse . and ..). The folder that needs to be excluded is aaa.
So when I run this script (every folder does have chmod 0777) it runs without errors, but the ZIP file doesn't show up. Why? And how can I solve this?
Thanks in advance!
have you tried to access the zip folder via PHP rather than looking in FTP as to whether it exists or not - as it might not appear immediately to view in FTP
function addFolderToZip($dir, $zipArchive, $zipdir = ''){
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
//Add the directory
if(!empty($zipdir)) $zipArchive->addEmptyDir($zipdir);
// Loop through all the files
while (($file = readdir($dh)) !== false) {
//If it's a folder, run the function again!
if(!is_file($dir . $file)){
// Skip parent and root directories, and any other directories you want
if( ($file !== ".") && ($file !== "..") && ($file !== "aa")){
addFolderToZip($dir . $file . "/", $zipArchive, $zipdir . $file . "/");
}
}else{
// Add the files
$zipArchive->addFile($dir . $file, $zipdir . $file);
}
}
}
}
}
After a while of fooling around this is what I found working. Use it as seen below.
$zipArchive = new ZipArchive;
$name = 'backups\backup_'. time() .'.zip';
$zipArchive->open($name, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE);
addFolderToZip($path, $zipArchive);
Here's my answer, checks if the modification time is greater then something as well.
<?php
$zip = new ZipArchive;
$zip_name = md5("backup".time()).".zip";
$res = $zip->open($zip_name, ZipArchive::CREATE);
$realpath = str_replace('filelist.php','',__FILE__);
$path = realpath('.');
$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);
foreach($objects as $name => $object){
if (is_file($object)) {
$file_count ++;
$epoch = $object->getMTime();
if($epoch>='1374809360'){ // Whatever date you want to start at
$array[] = str_replace($realpath,'',$object->getPathname());
}
}
}
foreach($array as $files) {
$zip->addFile($files);
}
$zip->close();
echo $zip_name.'-'.$file_count.'-'.$count_files;
?>

php readdir and is_dir

I am testing out the functions of directory handling. I have a fold/directory that contains the following:
0 File folder
false File folder
my_pictures File folder
MVI_3094 mov file
img01 jpeg image
etc...
I wrote the following code to traverse the directory and print out specific resutls
$handle = opendir("files/");
while(($entry = readdir($handle)) !== false)
{
if($entry == "." || $entry == "..")
{
continue;
}
if(is_dir($entry))
{
echo "Directory:$entry<br />";
}
}
My only problem is that the second "if" statement does not output the results of
echo "Directory:$entry<br />";
even though the entry is a directory. I have checked the entry manually with the "var_dump" function and it returns true as a directory.
Any suggestions would help
Try this and check. Just a try...
$handle = opendir("files/");
while(($entry = readdir($handle)) !== false)
{
if($entry == "." || $entry == "..")
{
continue;
}
elseif(is_dir("files/".$entry))
{
echo "Directory:$entry<br />";
}
}
$entry is relative... is_dir expects an absolute path.
Try:
if(is_dir("files/".$entry))
readdir() is just returning the filenames. Your code is therefore looking for the files in the current directory rather than the subdirectory.
This will just probe the basename of whatever directory entry:
is_dir($entry)
The opendir() result list will be relative to the directory you gave for reading. So you need to use:
is_dir("files/$entry")
Your problem is that in elseif(is_dir($entry)) {, entry is equal to some string like "file.txt" or "somedirectory", which isn't a path pointing to a file at all. It needs to be "files/file.txt".
Try this:
$dir = "files/";
$handle = opendir($dir);
while(($entry = readdir($handle)) !== false)
{
if($entry == "." || $entry == "..")
{
continue;
}
if(is_dir($dir.$entry))
{
echo "Directory:$entry<br />";
}
}
Try using the DirectoryIterator:
$iterator = new \DirectoryIterator(realpath('files/'));
foreach($iterator as $file){
if($file->isDot())
continue;
if($file->isDir())
printf('Directory: %s <br/>', $file->getRealPath());
}

problem in showing all files of a directory

hey guys im looking for a way to show all mp3 files in a directory
this is my code to get that :
if ($handle = opendir($dirPath)) {
while (false !== ($file = readdir($handle))) {
if ($file = ".mp3" && $file = "..") {
echo '
<track>
<location>'.$dirPath.$file.'</location>
<creator>'.$file.'</creator>
</track>
';
}
}
closedir($handle);
}
now i know that this script will only show mp3 files in parent directory , but i need to show all mp3 files in all directory inside parent directory
problem is this code cant show files inside sub directories !
That code won't work at all. As you are setting the $file variable to ".." the result will be a lot of xml containing $dirPath and "..".
This is what you are looking for :)
$it = new RecursiveDirectoryIterator('path/to/files/');
foreach (new RecursiveIteratorIterator($it) as $file)
{
echo $file->getPathname() . '<br />';
}
You'll have to make a recursive function to search for all the MP3s.
Also, you probably meant if ($file == ".mp3" && $file == "..") { instead of if ($file = ".mp3" && $file = "..") {, and after that's changed, you get a condition that's always false. What are you trying to do there?
like icktoofay said, you'll have to make a recursive function. also, your code has an error:
if ($file = ".mp3" && $file = "..") {
won't work (and if ($file == ".mp3" && $file == "..") { is wrong, too). that line should look like this:
if (substr($file,-4) == ".mp3" || $file == "..") {
if you want to show the ".." - else it's just like this:
if (substr($file,-4) == ".mp3") {

Get the files inside a directory

How to get the file names inside a directory using PHP?
I couldn't find the relevant command using Google, so I hope that this question will help those who are asking along the similar lines.
There's a lot of ways. The older way is scandir but DirectoryIterator is probably the best way.
There's also readdir (to be used with opendir) and glob.
Here are some examples on how to use each one to print all the files in the current directory:
DirectoryIterator usage: (recommended)
foreach (new DirectoryIterator('.') as $file) {
if($file->isDot()) continue;
print $file->getFilename() . '<br>';
}
scandir usage:
$files = scandir('.');
foreach($files as $file) {
if($file == '.' || $file == '..') continue;
print $file . '<br>';
}
opendir and readdir usage:
if ($handle = opendir('.')) {
while (false !== ($file = readdir($handle))) {
if($file == '.' || $file == '..') continue;
print $file . '<br>';
}
closedir($handle);
}
glob usage:
foreach (glob("*") as $file) {
if($file == '.' || $file == '..') continue;
print $file . '<br>';
}
As mentioned in the comments, glob is nice because the asterisk I used there can actually be used to do matches on the files, so glob('*.txt') would get you all the text files in the folder and glob('image_*') would get you all files that start with image_
The Paolo Bergantino's answer was fine but is now outdated!
Please consider the below official ways to get the Files inside a directory.
FilesystemIterator
FilesystemIterator has many new features compared to its ancestor DirectoryIterator as for instance the possibility to avoid the statement if($file->isDot()) continue;. See also the question Difference between DirectoryIterator and FilesystemIterator.
$it = new FilesystemIterator(__DIR__);
foreach ($it as $fileinfo) {
echo $fileinfo->getFilename() , PHP_EOL;
}
RecursiveDirectoryIterator
This snippet lists PHP files in all sub-directories.
$dir = new RecursiveDirectoryIterator(__DIR__);
$flat = new RecursiveIteratorIterator($dir);
$files = new RegexIterator($flat, '/\.php$/i');
foreach($files as $file) {
echo $file , PHP_EOL;
}
See also the Wrikken's answer.
Most of the time I imagine you want to skip . and ... Here is that with
recursion:
<?php
$o_dir = new RecursiveDirectoryIterator('.', FilesystemIterator::SKIP_DOTS);
$o_iter = new RecursiveIteratorIterator($o_dir);
foreach ($o_iter as $o_name) {
echo $o_name->getFilename();
}
https://php.net/class.recursivedirectoryiterator
The old way would be:
<?php
$path = realpath('.'); // put in your path here
$dir_handle = #opendir($path) or die("Unable to open $path");
$directories = array();
while ($file = readdir($dir_handle))
$directories[] = $file;
closedir($dir_handle);
?>
As already mentioned the directory iterator might be the better way for PHP 5.

Categories