问题
I have an directory tree which has been passed to array.
I would like to there empty folders inside this array.
How can I determine empty folders like /wp-content/uploads/2014/02/
and /wp-content/uploads/2014/
.
How can I delete them recursively.
Here is my array
array (
0 => './do-update.php',
5 => './wp-config.php',
6 => './wp-content/',
7 => './wp-content/uploads/',
8 => './wp-content/uploads/2013/',
9 => './wp-content/uploads/2013/05/',
10 => './wp-content/uploads/2013/05/kabeduvarkad-1024x768.jpg',
26 => './wp-content/uploads/2013/05/kabeduvarkad2.jpg',
27 => './wp-content/uploads/2013/10/',
28 => './wp-content/uploads/2014/',
29 => './wp-content/uploads/2014/02/',
30 => './wp-content/uploads/de.php',
31 => './wp-update.tar.gz',
32 => './wp-update/',
33 => './wp-update/wp-update.tar',
)
Thank you very much to Andresch Serj for him effords. Who wants to delete empty folders recursively with performance, you can use this solution.
function list_directory($dir) {
$file_list = array();
$stack[] = $dir;
while ($stack) {
$current_dir = array_pop($stack);
if ($dh = opendir($current_dir)){
while (($file = readdir($dh)) !== false) {
if ($file !== '.' AND $file !== '..') {
$current_file = "{$current_dir}/{$file}";
$report = array();
if (is_file($current_file)) {
$file_list[] = "{$current_dir}/{$file}";
} elseif (is_dir($current_file)) {
$stack[] = $current_file;
$file_list[] = "{$current_dir}/{$file}/";
}
}
}
}
}
sort($file_list, SORT_LOCALE_STRING);
return $file_list;
}
function remove_emptyfolders($array_filelist){
$files = array();
$folders = array();
foreach($array_filelist as $path){
// better performance for is_dir function
if ($path[strlen($path)-1] == '/'){ // check for last character if it is / which is a folder.
$folders[] = $path;
}
else{
$files[] = $path;
}
}
// bos olmayan klasorleri buluyoruz.
// eger klasor ismi dosya isimlerinin icerisinde gecmiyorsa bos demektir? right?
$folders_notempty = array();
foreach($files as $file){
foreach($folders as $folder){
if(strpos($file,$folder) !== false){
// dublicate olmasin diye key isimlerinin ismine yazdırdık.
$folders_notempty[$folder] = $folder;
}
}
}
// bos olmayanla klasorleri, digerlerinden cikariyoruz.
$folders_empty = array();
foreach($folders as $folder){
// eger bos olmayanlarin icerisinde bu dosya yoksa
if(!in_array($folder, $folders_notempty)){
$folders_empty[] = $folder;
}
}
// once en uzaktan silmeye baslamaliyiz. kisaca tersten.
$folders_empty = array_reverse($folders_empty);
$folders_deleted = array();
foreach($folders_empty as $k){
try{
$folders_deleted[$k] = 'NOT Succesfull';
if(rmdir($k)){ $folders_deleted[$k] = 'Deleted'; continue; }
chmod($k, 0777);
if(rmdir($k)){ $folders_deleted[$k] = 'Deleted after chmod'; }
}catch (Exception $e) {
print_r($e);
}
}
return $folders_deleted;
}
$files = list_directory(getcwd());
//print_r($files);
$files_deleted = remove_emptyfolders($files);
print_r($files_deleted);
回答1:
Simply iterate over your array using foreach.
foreach ($filesArray as $file) {
Then for each file, check if it is a folder using is_dir like this
if (is_dir ($file)) {
If it is a folder/directory, read the directory, for instanse using scandir.
$directoryContent = scandir($file);
If the result of scandir is empty, you have an empty folder that you can delete with unlink.
if (count($directoryContent) <= 2) { // checkig if there is moire than . and ..
unlink($file);
If you have trouble with unlink
, you may have to set file permissions accordingly.
If instead you need a function that recursively deletes empty subfolders given some paht, you should consider reading the SO question that was linkes in the comments.
EDIT
After taking into consideration your comments, what you do want is a function that deletes parent folders as well. So for a geiven level1/level2/level3
where level3
is empty and the only folder/file in level2
you want level2
to be deleted as well.
So from your example array, you want ./wp-content/uploads/2014/
deleted and not just ./wp-content/uploads/2014/10
, but only if ./wp-content/uploads/2014/10
has no content or subfolders with content.
So how to do that?
Simle: Extend your check for weather that folder is empty. If it is empty, manipoulate the given file/path string to get the parent folder. By now you should outsource this to a recursive functions indeed.
function doesDirectoryOnlyContainEmptyFolders($path) {
if(is_dir($path) {
$directoryContent = scandir($path);
if (count($directoryContent) <= 2) {
return true;
}
else {
foreach ($directoryContent as $subPath) {
if($filePath !== '.' && $filePath !== '..' && !doesDirectoryOnlyContainEmptyFolders($subPath)) {
return false;
}
}
return true;
}
}
return false;
}
So this function checks recursively if a path has only empty folders or folders containing empty folders - recursively. Now you want to check your paths and maybe delete them, recursively downwards and upwards.
function deleteEmptyFoldersRecursivelyUpAndDown($path) {
if (is_dir($path)) {
if(doesDirectoryOnlyContainEmptyFolders($path)) {
unlink($path);
$parentFolder = substr($path, 0, strripos ($path, '/'));
deleteEmptyFoldersRecursivelyUpAndDown($parentFolder);
}
else {
$directoryContent = scandir($path);
foreach ($directoryContent as $subPath) {
deleteEmptyFoldersRecursivelyUpAndDown($subPath);
}
}
}
}
If the given path is a directory, we check if it is empty using our recursive function. If it is, we delete it and recursively check the parent directory. If it is not, we iterate over its content to find empty folders, again calling the function itself recursively.
With these two function you have all you need. Simply iterate over your path array and use deleteEmptyFoldersRecursivelyUpAndDown
on all entries. If they are faulty, you'll manage to debug them i presume.
来源:https://stackoverflow.com/questions/23468751/finding-empty-folders-recursively-and-delete-them-recursively