目录的创建与删除是递归的一个经典应用。基本思路是:判断要创建的目录的父目录是否存在,存在则创建之,否则先创建父目录,依此递归,最后创建自己。删除相反,判断要删除的目录是否有子目录,有则先删除子目录,递归进行,最后删除自己。
递归创建目录
function mk_dir($path){
//当前目录本来就是存在,直接返回
if(is_dir($path)){
echo '创建OK';
return TRUE;
//当前目录不存在,但其父目录存在,创建之
}elseif(is_dir(dirname($path))){
return mkdir($path);
}else{
//其父目录也不存在,先创建其父目录,再创建之
mk_dir(dirname($path));//递归调用创建父目录
return mkdir($path);//创建自己
}
}
mk_dir('./a/b/c/d');
有另一种比较潇洒的写法,不是很好理解:
function mk_dir_1($path){
if(is_dir($path)){
echo '创建OK';
return TRUE;
}else{
//父目录已经存在或者创建了父目录,才执行创建操作
return is_dir(dirname($path))||mk_dir_1(dirname($path))?mkdir($path):false;
}
}
mk_dir_1('./b/c/d/e');
以上是应用递归思想一步一步的实现,实际在php中是可以递归创建的:
@mkdir('./aa/bb/cc',0777,true);//0777是最大访问权,true表示递归创建。@屏蔽目录已经存在的错误
递归删除目录
function delDir($path){
if(!is_dir($path)){
echo '不是目录';
return FALSE;
}
$dir = opendir($path);
//读取目录
while(($file = readdir($dir)) !== FALSE){
if($file == '.' || $file == '..'){
continue;//读到默认的点跳过,不用判断是否为目录或文件
}
//判断是否为普通文件
if(!is_dir($path.'/'.$file)){
unlink($path.'/'.$file);//是文件删除
echo '删除了', $path.'/'.$file;
}else{
delDir($path.'/'.$file);
}
}
closedir($dir);//要先关闭打开的目录才能删除
rmdir($path);
echo '成功删除目录:',$path,'';
}
delDir('./b');
跟创建不同,php中并没有递归删除目录的函数。rmdir()函数要求目录必须为空,且有相应权限。
迭代创建目录
隐约记得有这么一句话,迭代能做的事,递归都能做;递归能做的,迭代不一定能做。才疏学浅,不知道对错。就目录创建这件事,迭代该如何解决呢?
创建目录最终都是应用mkdir()函数,要求必须有父目录才能创建子目录,那么思路就是从根目录开始,逐级创建。这算迭代么?
function ddDir($path){
$arr=array();//先把需要创建的目录记录起来,一个一个的来创建
//该目录还不是目录,需要创建,记录下来
while(!is_dir($path)){
array_push($arr,$path);
$path=dirname($path);//往回找
}
while(!empty($arr)){
$dir=array_pop($arr);
mkdir($dir);//从第一级开始创建
}
}
ddDir('./a/b/c/d');
至于删除,迭代应该是无法解决。创建的时候其父目录只有一个且肯定是目录,而删除要判断其下面的内容是文件还是目录,且目录下面可能还有目录,不依靠递归是无法把所有要删除的目录和文件存储起来的,至少我是没有办法。这或许应了上面那句话。
目录遍历
目录的遍历,必须通过递归。
function listDir($path, $n, $deep = 1){
static $fileCount = 0;
static $dirCount = 0;
//当$n为0时遍历所有目录,具体正整数表示遍历深度
if($n !=0 && $deep > $n){
return;
}
$dir = opendir($path);
while(($file = readdir($dir)) !== FALSE){
if($file == '.' || $file == '..'){
continue;
}
if(is_dir($path.'/'.$file)){
$dirCount++;
echo str_repeat(" ", $deep).$file.'文件夹';
listDir($path.'/'.$file, $n, $deep+1);
}else{
$fileCount++;
echo str_repeat(" ", $deep).$file.'';
}
}
if($deep == 1){
echo '
共'.$dirCount.'个文件夹,',$fileCount.'个文件
';
}
}
listDir('E:\wordpress', 3);
以上遍历一个wordpress目录最深到第3层,结果如下:
index.php
license.txt
readme.html
wp-activate.php
wp-admin文件夹
about.php
admin-ajax.php
admin-footer.php
admin-functions.php
admin-header.php
admin-post.php
admin.php
async-upload.php
comment.php
credits.php
css文件夹
color-picker-rtl.css
color-picker-rtl.
...
...
wp-settings.php
wp-signup.php
wp-trackback.php
xmlrpc.php
共49个文件夹,658个文件
str_repeat()中重复的是空格“ ”,被吞无法显示。
注意输出数量统计的时候要判断当前深度,否则每递归每到底一次输出一次统计信息。
要列出某个目录下的所有文件和文件夹(只列第一层,不递归),php有现成函数scandir(),返回一个枚举数组包含所有文件和文件夹,包括’.’和’..’。
再乱入一段。
迭代的一个经典应用是累加累乘。看过这么一个帖子,一个工作几年的人去面试叫用递归计算1~100的和,瞬间愣了。该如何写呢?这在递归里就是所谓的“耍赖”,叫我算1~100不会,但我知道它等于1~99加100,1~99也不会但知道是1~98加99…。代码如下:
function digui($n){
if($n<=1){
return 1;
}
return digui($n-1)+$n;
}
echo digui(100);