这里我也把源代码贴一下,方便大家浏览
/* deltree.h */
#ifndef __DELTREE_H
#define __DELTREE_H
// 调试宏
//#define __DEBUG
#define MAX_STACK_SIZE 1024
typedef enum { tpFile, tpDir } ATTRIB_T;
typedef enum { False = 0, True } BOOL_T;
typedef struct tagFileNode {
ATTRIB_T oFSAttr; // 节点类型(tpFile = 文件, tpDir = 目录)
char *pFName; // 文件名(当tpDir时,为目录名)
struct tagFileNode *pParent; // 父节点
struct tagFileNode *pNext; // 子节点链表
struct tagFileNode *pPrev;
struct tagFileNode *pDesecentHead; // 下一层节点
struct tagFileNode *pDesecentTail;
} ATTR_FS_TREE_NODE;
// 将物理路径(就是硬文件系统)映射到内存路径树(对应该软件的数据结构)
ATTR_FS_TREE_NODE *DrawPhy2LogTree( char *path ) {
int done;
int len;
int top = (int)-1;
struct ffblk ffblk;
// 临时字符串,为了创建查找使用串而设立
char *pTempStr;
// 最大文件夹数
ATTR_FS_TREE_NODE *pStack[MAX_STACK_SIZE];
// 临时节点指针
ATTR_FS_TREE_NODE *pTemp;
ATTR_FS_TREE_NODE *p;
// 路径根
ATTR_FS_TREE_NODE *pRoot = (ATTR_FS_TREE_NODE *)malloc(sizeof(ATTR_FS_TREE_NODE));
assert( pRoot );
if( path == (char *)0 )
return (ATTR_FS_TREE_NODE *)0;
// 创建根
pRoot->pFName = new char[strlen(path)+1];
strcpy( pRoot->pFName, path );
pRoot->oFSAttr = tpDir;
// 初始化根节点
pRoot->pDesecentHead = (ATTR_FS_TREE_NODE *)0;
pRoot->pDesecentTail = (ATTR_FS_TREE_NODE *)0;
pRoot->pNext = (ATTR_FS_TREE_NODE *)0;
pRoot->pPrev = (ATTR_FS_TREE_NODE *)0;
pRoot->pParent = (ATTR_FS_TREE_NODE *)0;
// 压栈处理(这里为了效率不用递归遍历路径)
pStack[++top] = pRoot;
while( top >= (int)0 ) {
// 取出需要处理的路径
pTemp = pStack[top--];
// 构造查找串,这里我们查找所有文件或目录,在结尾添加"\*.*"即可
len = strlen(pTemp->pFName);
pTempStr = new char[len + 5];
strcpy( pTempStr, pTemp->pFName );
strcat( pTempStr, "\\*.*" );
// 进行文件夹与文件的搜索(包含隐藏文件、只读文件,但不包含系统文件)
done = findfirst( pTempStr, &ffblk, FA_NORMAL | FA_DIREC | FA_RDONLY | FA_HIDDEN );
while( !done ) {
// 测试当前获取的路径或文件名是否有效
// "." 或 ".."都不是我们需要的路径
if( ffblk.ff_name[0] == '.' ) {
done = findnext( &ffblk );
continue;
}
// 保存文件夹到当前正在处理的节点
// 当前节点没有子节点
if( pTemp->pDesecentHead == (ATTR_FS_TREE_NODE *)0 ) {
pTemp->pDesecentHead = (ATTR_FS_TREE_NODE *)malloc(sizeof(ATTR_FS_TREE_NODE));
assert( pTemp->pDesecentHead );
p = pTemp->pDesecentHead;
// 填充节点内容
p->pFName = (char *)malloc(sizeof(char) * (len + strlen(ffblk.ff_name) + 2));
assert(p->pFName);
strcpy( p->pFName, pTemp->pFName ); // len个字节
strcat( p->pFName, "\\" ); // 1个字节
strcat( p->pFName, ffblk.ff_name ); // strlen(ffblk.ff_name) + 1个字节
// 判断是否为文件夹
if( ffblk.ff_attrib != FA_DIREC )
p->oFSAttr = tpFile;
else {
// 将新添加的目录压栈
pStack[++top] = p;
p->oFSAttr = tpDir;
}
p->pDesecentHead = (ATTR_FS_TREE_NODE *)0;
p->pDesecentTail = (ATTR_FS_TREE_NODE *)0;
p->pNext = (ATTR_FS_TREE_NODE *)0;
p->pPrev = (ATTR_FS_TREE_NODE *)0;
p->pParent = pTemp;
pTemp->pDesecentTail = p;
}
// 当前节点有子节点
else {
pTemp->pDesecentTail->pNext = (ATTR_FS_TREE_NODE *)malloc(sizeof(ATTR_FS_TREE_NODE));
p = pTemp->pDesecentTail->pNext;
assert(p);
p->pFName = (char *)malloc(sizeof(char) * (len + strlen(ffblk.ff_name) + 2));
assert(p->pFName);
strcpy( p->pFName, pTemp->pFName );
strcat( p->pFName, "\\" );
strcat( p->pFName, ffblk.ff_name );
if( ffblk.ff_attrib != FA_DIREC )
p->oFSAttr = tpFile;
else {
pStack[++top] = p;
p->oFSAttr = tpDir;
}
p->pDesecentHead = (ATTR_FS_TREE_NODE *)0;
p->pDesecentTail = (ATTR_FS_TREE_NODE *)0;
p->pNext = (ATTR_FS_TREE_NODE *)0;
p->pPrev = pTemp->pDesecentTail;
pTemp->pDesecentTail->pNext = p;
p->pParent = pTemp;
pTemp->pDesecentTail = p;
}
// 继续往下搜索
done = findnext( &ffblk );
}
delete []pTempStr;
pTempStr = (char *)0;
}
// 完成后返回根路进
return pRoot;
}
// 删除指定目录树
void DelTree( ATTR_FS_TREE_NODE *pRoot ) {
int top = (int)-1;
ATTR_FS_TREE_NODE *pStack[MAX_STACK_SIZE];
ATTR_FS_TREE_NODE *pTemp, *p;
BOOL_T flag; // 鉴定指定层是否有下一级目录
pStack[++top] = pRoot;
while( top >= (int)0 ) {
flag = False; // 假设该层没有下一级目录
pTemp = pStack[top--];
// 消除该层文件,并将该层的子目录进栈
p = pTemp->pDesecentHead;
while( p != (ATTR_FS_TREE_NODE *)0 ) {
if( p->oFSAttr == tpDir ) { //若是目录则进栈
if( flag != True ) { // 该操作必须在子目录压栈前操作
flag = True;
pStack[++top] = pTemp; // 重新将带有子目录的根目录压栈为了以后的目录删除操作
}
pStack[++top] = p;
p = p->pNext;
}
else { //若是文件删除
// 调试状态下不进行删除操作,为了数据安全
#ifndef __DEBUG
unlink(p->pFName);
#endif
printf("%s has been deleted!\n", p->pFName);
// 删除该节点
if( p->pPrev != (ATTR_FS_TREE_NODE *)0 )
p->pPrev->pNext = p->pNext;
if( p->pNext != (ATTR_FS_TREE_NODE *)0 )
p->pNext->pPrev = p->pPrev;
if( p == pTemp->pDesecentHead )
pTemp->pDesecentHead = p->pNext;
else if( p == pTemp->pDesecentTail ) {
if( p->pPrev != (ATTR_FS_TREE_NODE *)0 )
p->pPrev->pNext = (ATTR_FS_TREE_NODE *)0;
pTemp->pDesecentTail = p->pPrev;
}
// 暂时将p->pNext压栈进行删除操作
pStack[++top] = p->pNext;
// 删除名称项
free(p->pFName);
free(p);
p = pStack[top--];
}
}
// 说明该目录没有下一层子目录,直接删除该目录
if( flag == False ) {
#ifndef __DEBUG
rmdir( pTemp->pFName );
#endif
printf("[%s] has been removed!\n", pTemp->pFName);
p = pTemp->pParent;
if( pTemp->pPrev != (ATTR_FS_TREE_NODE *)0 )
pTemp->pPrev->pNext = pTemp->pNext;
if( pTemp->pNext != (ATTR_FS_TREE_NODE *)0 )
pTemp->pNext->pPrev = pTemp->pPrev;
if( p != (ATTR_FS_TREE_NODE *)0 ) {
if( pTemp == p->pDesecentHead )
p->pDesecentHead = pTemp->pNext;
else if( pTemp == p->pDesecentTail ) {
if( pTemp->pPrev != (ATTR_FS_TREE_NODE *)0 )
pTemp->pPrev->pNext = (ATTR_FS_TREE_NODE *)0;
p->pDesecentTail = pTemp->pPrev;
}
}
free(pTemp->pFName);
free(pTemp);
}
}
}
#ifdef __DEBUG
// 先序遍历文件树
void DisplayTree( ATTR_FS_TREE_NODE *pRoot ) {
ATTR_FS_TREE_NODE *p;
ATTR_FS_TREE_NODE *pStack[MAX_STACK_SIZE];
int top = (int)-1;
pStack[++top] = pRoot;
while( top >= (int)0 ) {
p = pStack[top--];
printf("[%s]\n",p->pFName);
p = p->pDesecentHead;
while( p != (ATTR_FS_TREE_NODE *)0 ) {
if( p->oFSAttr == tpDir )
//DisplayTree( p );
pStack[++top] = p;
else
printf("%s\n", p->pFName);
p = p->pNext;
}
}
}
#endif
#endif
/* deltree.cpp */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include <dir.h>
#include <conio.h>
#include "deltree.h"
int main(int argc, char *argv[]) {
ATTR_FS_TREE_NODE *pRoot;
int i, j;
int len, done;
struct ffblk ffblk;
char c;
if( argc != (int)2 ) {
printf("Deltree simple version\n");
printf("Usage: %s <directory>\n\n", argv[0]);
printf("eg. %s d:\\testdir\n", argv[0]);
printf("[NOTICE] Delete any logical driver root is forbidden!\n");
}
else {
// 判断是否为逻辑盘根
if( strlen(argv[1]) == (int)2 && argv[1][1] == ':' ) {
printf("Delete any logical driver root is forbidden!\n");
}
else {
// 收集路径
len = i = strlen(argv[1]) - 1;
while( argv[1][i--] != '\\' && i >= 0 );
// 若路径长度大于8则自动缩进
if( (j = (len - i - 1)) > 8 ) {
argv[1][ (j = (i + 1 + (j - 8) + 6)) ] = '~';
argv[1][++j] = '1';
argv[1][++j] = '\0';
}
// 确认是否要删除,为了安全考虑
do {
printf("Do you really want to REMOVE [%s] and its sub-directories within all files? (Y/N) ", argv[1]);
c = getchar();
} while( c != 'Y' && c != 'y' && c != 'N' && c != 'n' );
if( c == 'N' || c == 'n' )
return (int)0;
// 查看指定路径是否存在
done = findfirst( argv[1], &ffblk, FA_DIREC );
if(!done) { //指定路径存在
pRoot = DrawPhy2LogTree( argv[1] );
DelTree( pRoot );
pRoot = (ATTR_FS_TREE_NODE *)0;
printf("\nAll done!\n");
}
else
printf("Path not found!\n");
}
}
return 0;
}