How about this function?
What does foreach and rmdir($file) do in this code?
function rmDirectory($dir)
{
foreach (glob($dir . '/*') as $file) {
if (is_dir($file))
rmdir($file);
else
unlink($file);
}
rmdir($dir);
}
The foreach construct provides an easy way to iterate over arrays of $dir.
glob — Find pathnames matching a pattern
rmdir — Removes directory
Delete all files and empty directories under $dir
If the $dir is empty, delete it
The glob() function returns an array of filenames or directories
matching a specified pattern.
Source. Your foreach traverses each items found at the pattern specified as parameter. For each of them, is_dir checks whether they are directories. If the current $file happens to be a directory, then it is removed using rmdir, otherwise it is a file and is removed using unlink. Finally $dir is removed as well.
rmDirectory essentially removes the content (folders and files) of a directory and then removes the directory itself.
Related
Below is my attempt to delete a folder and all its content. A folder may contain zip files and folders with files.
public function deleteFolder($dir){
if(file_exists($dir)){
$it = new \RecursiveDirectoryIterator($dir, \RecursiveDirectoryIterator::SKIP_DOTS);
$files = new \RecursiveIteratorIterator($it,
\RecursiveIteratorIterator::CHILD_FIRST);
foreach($files as $file) {
if ($file->isDir()){
rmdir($file->getRealPath());
} else {
unlink($file->getRealPath());
}
}
rmdir($dir);
}
}
but it returns the following error:
rmdir(C:\Juliver\UIUX\pd-loader\loader/temp/utso-pulgada-pd-loader-5066a7e0298a):
Directory not empty in C:\Juliver\UIUX\pd-loader\loader\Patcher.php on line 95
line 95 points to rmdir($dir); line
If I check the folder utso-pulgada-pd-loader-5066a7e0298a, I see that it's already empty but it throws me the above error.
$dirname = 'C:/Users/Admin/Desktop/test';
array_map('unlink', glob("$dirname/*.*"));
rmdir($dirname);
try this, this remove all the file present in the folder, and that folder too
Directory may contain other directories so you have to use a recursive function.
function removeDir($path) {
$files = glob("$path/*");
foreach ($files as $file) {
if (is_dir($file)) {
removeDir($file);
} else {
unlink($file);
}
}
rmdir($path);
}
Now is enough to call removeDir("/my/nice/path");
If you see the directory already empty, try to check for hidden files and be sure that you have the right permissions.
I suspect you have already checked its not a file permissions issue. As your code works for me but not you, it makes me wonder if it is a to do with PHP file stat or Real Path caching.
Unlinking a file should clear stat cache for individual file automatically. However PHP bugs have previously been known to cause this issue with rmdir.
Try doing a clearstatcache after the rmdir statement in your foreach block.
Previously I've used glob (mentioned in other answers) so I've no idea how RecursiveDirectoryIterator works re file handles; as a long shot try destroying these objects ( unset($files); unset($it) ) before your final rmdir.
If use this function to remove a directory + all files inside.
function delete_files($target)
{
if(is_dir($target))
{
$files = glob($target . '*', GLOB_MARK);
foreach($files as $file)
{
delete_files($file);
}
rmdir($target);
}
elseif(is_file($target))
{
unlink($target);
}
}
delete_files($directory);
But whenever I do this, I get this error message:
Warning: rmdir(directory/12) [function.rmdir]: No such file or directory
in delete_files.php
"directory/12" is the correct name of the directory I wanted to delete. I don't understand why it says that it does not exist because it does! Weirdly though, even though I got the error message, the directory DID get deleted.
So I added a line of code print_n($files); before the for-loop and it game me two arrays -- one containing the directory ("directory/12") and the other containing all the files of the directory ("directory/12/01.gif", "directory/12/02.gif" etc). So I figured the directory must have gotten deleted in the for-loop and removed the line rmdir($target) and tried it again. This time, all the files within the directory got deleted but the directory itself remained.
So apparently, rmdir DOES indeed remove the directory correctly. But then, why does it give me the error message beforehand that it doesn't exist?
It will work if you append a slash to the directory name.
Explanation: When you initially call the function as delete_files("directory/12"), the parameters passed to the glob() call will look like this:
$files = glob("directory/12*", GLOB_MARK);
Assuming that you have no other files in directory/ with names beginning with 12, this will just return "directory/12/" (with a slash appended because of GLOB_MARK). The function will then recursively call itself with that parameter, resulting in the top-level directory being processed twice.
Of course, if you did happen to have some other file or directory named, say, directory/123, then it would also get deleted, which is presumably not what you want.
To fix this properly, you should make sure your function can properly handle directories even if they get passed in without a trailing slash. The simplest way to do that would be to always append the slash to directory names before globbing them, like this:
$files = glob($target . '/*');
However, note that this could still fail (albeit less destructively) if your directory happened to contain some files not matched by *, such as dotfiles, since they would not get deleted, causing the subsequent rmdir() to fail because the directory will not be empty.
A more robust solution would be to use scandir() instead of glob(), like this:
$files = array_diff( scandir($target), array('.', '..') );
foreach ($files as $file) {
delete_files("$target/$file");
}
(The array_diff() is needed to eliminate the special . and .. directory entries, which would cause the code to recurse forever if they weren't excluded.)
One remaining potential failure mode is that this code will happily follow symlinks to directories and try to delete everything in the directory they point to (and then fail to remove the link itself, because rmdir() can't remove symlinks). To fix this issue, you'll probably want to replace the is_dir($target) test with !is_link($target) && is_dir($target).
All put together, the resulting code would look like this:
function delete_files($target)
{
if(!is_link($target) && is_dir($target))
{
// it's a directory; recursively delete everything in it
$files = array_diff( scandir($target), array('.', '..') );
foreach($files as $file) {
delete_files("$target/$file");
}
rmdir($target);
}
else
{
// probably a normal file or a symlink; either way, just unlink() it
unlink($target);
}
}
delete_files($directory);
Ps. See also How do I recursively delete a directory and its entire contents (files + sub dirs) in PHP?
cause you call it twice the first time it works the second time it gives a error.
I can't prove it, but with recursive code like that it is the problem.
Simple question - How to list .htaccess files using glob()?
glob() does list "hidden" files (files starting with . including the directories . and ..), but only if you explicitly ask it for:
glob(".*");
Filtering the returned glob() array for .htaccess entries with preg_grep:
$files = glob(".*") AND $files = preg_grep('/\.htaccess$/', $files);
The alternative to glob of course would be just using scandir() and a filter (fnmatch or regex):
preg_grep('/^\.\w+/', scandir("."))
in case any body come to here,
since the SPL implemented in PHP, and offers some cool iterators, you may make use of the to list your hidden files such as .htaccess files or it's alternative hidden linux files.
using DirectoryIterator to list all of directory contents and excluding the . and .. as follows:
$path = 'path/to/dir';
$files = new DirectoryIterator($path);
foreach ($files as $file) {
// excluding the . and ..
if ($file->isDot() === false) {
// make some stuff
}
}
I want to to destroy all images within a folder with PHP how can I do this?
foreach(glob('/www/images/*.*') as $file)
if(is_file($file))
#unlink($file);
glob() returns a list of file matching a wildcard pattern.
unlink() deletes the given file name (and returns if it was successful or not).
The # before PHP function names forces PHP to suppress function errors.
The wildcard depends on what you want to delete. *.* is for all files, while *.jpg is for jpg files. Note that glob also returns directories, so If you have a directory named images.jpg, it will return it as well, thus causing unlink to fail since it deletes files only.
is_file() ensures you only attempt to delete files.
The easiest (non-recursive) way is using glob():
$files = glob('folder/*.jpg');
foreach($files as $file) {
unlink($file);
}
$images = glob("images/*.jpg");
foreach($images as $image){
#unlink($image);
}
use unlink and glob function
for more see this link
http://php.net/manual/en/function.unlink.php
and
http://php.net/manual/en/function.glob.php
I'm trying to design a program in PHP that would allow me to find files with specific file extensions (example .jpg, .shp etc) in a known directory which consists of multiple folders.
Sample code, documentation or information about what methods I will be required to use will be much appreciated.
glob is pretty easy:
<?php
foreach (glob("*.txt") as $filename) {
echo "$filename size " . filesize($filename) . "\n";
}
?>
There are a few suggestions for recursive descent at the readdir page.
Take a look at PHP's SPL DirectoryIterator.
I believe PHP's glob() function is exactly what you are looking for:
http://php.net/manual/en/function.glob.php
Use readdir to get a list of files, and fnmatch to work out if it matches your required filename pattern. Do all this inside a function, and call your function when you find directories. Ask another question if you get stuck implementing this (or comment if you really have no idea where to start).
glob will get you all the files in a given directory, but not the sub directories. If you need that too, you will need to: 10. get recursive, 20. goto 10.
Here's the pseudo pseudocode:
function getFiles($pattern, $dir) {
$files = glob($dir . $pattern);
$folders = glob($dir, GLOB_ONLYDIR);
foreach ($folders as $folder) {
$files = $files + getFiles($folder);
}
return $files;
}
The above will obviously need to be tweaked to get it working, but hopefully you get the idea (remember not to follow directory links to ".." or "." or you'll be in infinite loop town).