将源目录中的文件按照前缀分发到不同目录中的算法设计及C代码实现
来源:互联网 发布:南师大图书馆数据库 编辑:程序博客网 时间:2024/05/22 17:32
一、需求描述
在Linux系统的某个源目录中有一批后缀相同的文件,编写程序将这些文件按照前缀分发到不同的目录中。
例如,源目录SourceDir中存放有三个后缀相同的文件File1_1.txt、File2_1.txt和File3_1.txt,按照前缀File1_、File2_和File3_将它们分别移动(分发)到目录FileDir1、FileDir2和FileDir3中。
二、算法设计
基于需求,可以采用如图1所示的程序流程:
图1 程序总体流程
三、特殊流程考虑
在编写程序的过程中,对于某些特殊流程的考虑如下:
1.如果扫描源目录出错,则直接停止程序的运行,而不用继续扫描下一个目录。
2.对于某些空文件(即文件的大小为0),直接在源目录中将其删除,而不用进行分发。
3.为了随时能够处理放到源目录中的文件,程序每隔一段时间(如一分钟)扫描一次源目录。也就是说,如果不人为操作,程序启动之后会不停地运行。
四、程序代码
/*********************************************************************** 版权所有 (C)2016, Zhou Zhaoxiong。** 文件名称:FileDistribute.c* 文件标识:无* 内容摘要:将某个目录中的文件按照前缀分发到对应的目录中* 其它说明:无* 当前版本:V1.0* 作 者:Zhou Zhaoxiong* 完成日期:20160517***********************************************************************/#include <stdio.h>#include <string.h>#include <dirent.h>#include <ftw.h>#include <time.h>// 重定义数据类型typedef signed int INT32;typedef unsigned int UINT32;typedef unsigned char UINT8;// 全局变量定义UINT8 g_szSourceDir[256] = {0}; // 源文件的目录// 函数声明INT32 SelectFlies(struct dirent *pDir);void ScanDirAndDistribute(void);void Sleep(UINT32 iCountMs);/***************************************************************** 功能描述: 主函数* 输入参数: 无* 输出参数: 无* 返 回 值: 0-执行完成* 其他说明: 无* 修改日期 版本号 修改人 修改内容* -------------------------------------------------------------* 20160517 V1.0 Zhou Zhaoxiong 创建****************************************************************/INT32 main(void){ // 源文件的目录 snprintf(g_szSourceDir, sizeof(g_szSourceDir)-1, "%s/zhouzx/TestDir/SourceDir", getenv("HOME")); // 调用函数执行文件的分发 while (1) { ScanDirAndDistribute(); Sleep(60 * 1000); // 每一分钟执行一次文件的分发 } return 0;}/*********************************************************************** 功能描述:根据后缀选择文件* 输入参数:dir-目录* 输出参数:无* 返 回 值:0-失败 1-成功* 其它说明:一个形如test.txt的文件要被扫描出来, 而形如test的文件不符合条件* 修改日期 版本号 修改人 修改内容* --------------------------------------------------------------------* 20160517 V1.0 ZhouZhaoxiong 创建***********************************************************************/INT32 SelectFlies(struct dirent *pDir){ if (pDir == NULL) { printf("SelectFlies:input parameter is NULL!\n"); return 0; } // 根据.txt(后缀)选择文件 if (strstr(pDir->d_name, ".txt") != NULL) { return 1; // 找到了满足条件的文件 } else { return 0; }}/*********************************************************************** 功能描述:扫描目录并分发文件* 输入参数:无* 输出参数:无* 返 回 值:无* 其它说明:无* 修改日期 版本号 修改人 修改内容* --------------------------------------------------------------------* 20160517 V1.0 ZhouZhaoxiong 创建***********************************************************************/void ScanDirAndDistribute(void){ INT32 iScanDirRet = 0; UINT32 iFileIdx = 0; UINT32 iFileCount = 0; UINT32 iFileSize = 0; UINT8 szFileDir[256] = {0}; UINT8 szScanedFile[512] = {0}; UINT8 szCmdBuf[256] = {0}; FILE *fp = NULL; struct dirent **ppDirEnt = NULL; // 扫描源目录, 并分发文件 iScanDirRet = scandir(g_szSourceDir, &ppDirEnt, SelectFlies, alphasort); if (iScanDirRet < 0) // 扫描目录出错 { printf("ScanDirAndDistribute:exec scandir failed, path=%s\n", g_szSourceDir); return; } else if (iScanDirRet == 0) // 目录下无文件 { printf("ScanDirAndDistribute:no satisfied file in directory %s\n", g_szSourceDir); } else // 将满足条件的文件移动到对应的目录中 { for (iFileIdx = 0; iFileIdx < iScanDirRet; iFileIdx ++) { // 先判断扫描到的文件是否为空文件, 是则直接删除, 不是才执行移动的操作 memset(szScanedFile, 0x00, sizeof(szScanedFile)); snprintf(szScanedFile, sizeof(szScanedFile) - 1, "%s/%s", g_szSourceDir, ppDirEnt[iFileIdx]->d_name); fp = fopen(szScanedFile, "r"); if (fp == NULL) // 打开文件失败, 直接返回 { printf("ScanDirAndDistribute:open file %s failed, please check!\n", szScanedFile); return; } fseek(fp, 0, SEEK_END); iFileSize = ftell(fp); if (iFileSize == 0) // 该文件为空文件 { printf("ScanDirAndDistribute:%s is an empty file, so delete it directly!\n", szScanedFile); memset(szCmdBuf, 0x00, sizeof(szCmdBuf)); snprintf(szCmdBuf, sizeof(szCmdBuf) - 1, "rm %s", szScanedFile); system(szCmdBuf); } else // 根据前缀将文件移动(分发)到对应的目录中 { if (strncmp(ppDirEnt[iFileIdx]->d_name, "File1_", strlen("File1_")) == 0) // 移动到FileDir1 { memset(szFileDir, 0x00, sizeof(szFileDir)); snprintf(szFileDir, sizeof(szFileDir)-1, "%s/zhouzx/TestDir/FileDir1", getenv("HOME")); } else if (strncmp(ppDirEnt[iFileIdx]->d_name, "File2_", strlen("File2_")) == 0) // 移动到FileDir2 { memset(szFileDir, 0x00, sizeof(szFileDir)); snprintf(szFileDir, sizeof(szFileDir)-1, "%s/zhouzx/TestDir/FileDir2", getenv("HOME")); } else if (strncmp(ppDirEnt[iFileIdx]->d_name, "File3_", strlen("File3_")) == 0) // 移动到FileDir3 { memset(szFileDir, 0x00, sizeof(szFileDir)); snprintf(szFileDir, sizeof(szFileDir)-1, "%s/zhouzx/TestDir/FileDir3", getenv("HOME")); } else // 前缀不满足, 直接将该文件删掉 { memset(szCmdBuf, 0x00, sizeof(szCmdBuf)); snprintf(szCmdBuf, sizeof(szCmdBuf) - 1, "rm %s", szScanedFile); system(szCmdBuf); printf("ScanDirAndDistribute:now, %s\n", szCmdBuf); continue; // 继续判断下一个 } memset(szCmdBuf, 0x00, sizeof(szCmdBuf)); snprintf(szCmdBuf, sizeof(szCmdBuf) - 1, "mv %s %s", szScanedFile, szFileDir); system(szCmdBuf); printf("ScanDirAndDistribute:now, %s\n", szCmdBuf); iFileCount ++; } } } printf("ScanDirAndDistribute:this time,totally moved %d file(s).\n", iFileCount); return;}/*********************************************************************** 功能描述: 程序休眠* 输入参数: iCountMs-休眠时间(单位:ms)* 输出参数: 无* 返 回 值: 无* 其它说明: 无* 修改日期 版本号 修改人 修改内容* ------------------------------------------------------------------* 20160517 V1.0 Zhou Zhaoxiong 创建********************************************************************/ void Sleep(UINT32 iCountMs){ struct timeval t_timeout = {0}; if (iCountMs < 1000) { t_timeout.tv_sec = 0; t_timeout.tv_usec = iCountMs * 1000; } else { t_timeout.tv_sec = iCountMs / 1000; t_timeout.tv_usec = (iCountMs % 1000) * 1000; } select(0, NULL, NULL, NULL, &t_timeout); // 调用select函数阻塞程序}
五、程序测试
将编写好的程序“FileDistribute.c”上传到Linux机器,并使用“gcc -g -o FileDistribute FileDistribute.c”命令对该程序进行编译,生成“FileDistribute”文件。下面对程序进行详细的测试。
1.在启动程序之前,在源目录SourceDir中放入文件File1_1.txt、File2_1.txt和File3_1.txt,程序运行情况如下:
ScanDirAndDistribute:now, mv /home/zhou/zhouzx/TestDir/SourceDir/File1_1.txt /home/zhou/zhouzx/TestDir/FileDir1ScanDirAndDistribute:now, mv /home/zhou/zhouzx/TestDir/SourceDir/File2_1.txt /home/zhou/zhouzx/TestDir/FileDir2ScanDirAndDistribute:now, mv /home/zhou/zhouzx/TestDir/SourceDir/File3_1.txt /home/zhou/zhouzx/TestDir/FileDir3ScanDirAndDistribute:this time,totally moved 3 file(s).
可以看到,源目录中的三个文件已经没有了,它们被分别移动到了结果目录FileDir1、FileDir2和FileDir3中:
~/zhouzx/TestDir/SourceDir> lltotal 0~/zhouzx/TestDir/FileDir1> ll-rw------- 1 zhou users 12 2016-05-17 18:58 File1_1.txt~/zhouzx/TestDir/FileDir2> ll-rw------- 1 zhou users 12 2016-05-17 18:58 File2_1.txt~/zhouzx/TestDir/FileDir3> ll-rw------- 1 zhou users 12 2016-05-17 18:58 File3_1.txt
2.一段时间之后,在源目录SourceDir中放入文件File4_1.txt,程序运行情况如下:
ScanDirAndDistribute:now, rm /home/zhou/zhouzx/TestDir/SourceDir/File4_1.txtScanDirAndDistribute:this time,totally moved 0 file(s).
可以看到,因为前缀不匹配,File4_1.txt文件直接被删除掉了。
~/zhouzx/TestDir/SourceDir> lltotal 0
3.一段时间之后,在源目录SourceDir中放入空文件File_7.txt、File_8.txt和File_9.txt,程序运行情况如下:
ScanDirAndDistribute:/home/zhou/zhouzx/TestDir/SourceDir/File_7.txt is an empty file, so delete it directly!ScanDirAndDistribute:/home/zhou/zhouzx/TestDir/SourceDir/File_8.txt is an empty file, so delete it directly!ScanDirAndDistribute:/home/zhou/zhouzx/TestDir/SourceDir/File_9.txt is an empty file, so delete it directly!ScanDirAndDistribute:this time,totally moved 0 file(s).
可以看到,源目录SourceDir中的空文件已经被全部删除掉了。
~/zhouzx/TestDir/SourceDir> lltotal 0
六、需求扩展
基于本文中的需求和程序,可考虑对需求进行以下扩展:
1.在移动(分发)文件之前,先查看相同文件名的文件在对应结果目录中是否存在,如果存在,则直接将该文件在源目录中删除掉;如果不存在,才将该文件移动到对应结果目录中。
2.为避免结果目录中的文件过多,可以在程序中添加清理机制,即将存放时间超过一定时长的文件删除掉。
3.为了体现程序的灵活性,可将部分文件信息(如文件前缀、后缀、存放目录、扫描间隔时长等)存放到配置文件中,程序在启动时读取相关的配置项的值来执行后续目录扫描和文件分发的操作。
- 将源目录中的文件按照前缀分发到不同目录中的算法设计及C代码实现
- 将前缀和后缀相同的文件移动到同一个目录的算法设计及C代码实现
- ubuntu 用shell脚本实现将当前目录下所有目录中的某一类文件拷贝到同一目录下
- 将IE缓存中的文件copy到其它目录下
- 将assets中的文件拷到指定目录
- Perl 将一目录下的文件按照文件名中的时间字符串排序
- 【字符串处理算法】将输入字符串中的各个单词反序的算法设计及C代码实现
- Windows中的目录及文件
- DEMO:查找c盘中的所有目录及文件
- Python中的文件和目录操作实现代码
- Python中的文件和目录操作实现代码
- Python中的文件和目录操作实现代码
- Python中的文件和目录操作实现代码
- Python中的文件和目录操作实现代码
- Linux下c语言实现将一个目录下的所有文件和目录复制到另一个目录下
- Linux下c语言实现将一个目录下的所有文件和目录复制到另一个目录下
- Linux下c语言实现将一个目录下的所有文件和目录复制到另一个目录下
- 迭代目录将目录及其子目录中的文件输出
- 微信公众号第三方平台开发PYTHON教程 PART 2
- sqlserver中user是一个关键字,不要用它作为表名,否则会报错。
- 【Unity】今天研究了一个基于Blur的文字外发光(文字描边)shader
- POJ 3132 Sum of Different Primes
- 反射详解
- 将源目录中的文件按照前缀分发到不同目录中的算法设计及C代码实现
- 微信公众号第三方平台开发PYTHON教程 PART 3
- @property 和@synthesize
- javascript笔试题(2)
- 【POJ 2398】Toy Storage(计算几何)
- 声学特征(四) pitch-yin代码实现
- Core Data入门
- 【EF系列】EntityFrameWork实体关系映射
- [SDOI2016]sequence 解题报告