查找并重命名文件
下面是实现查找并重命名文件的C程序,使用了apue.h库中的函数和数据结构。 该程序支持查找指定目录下的所有文件,并将指定文件名的文件重命名为"pass"。 程序会输出重命名的文件数量。 点击展开/折叠代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 #include "apue.h" #include <dirent.h> #include <limits.h> #include <string.h> #include <sys/stat.h> #include <sys/types.h> #include <stdio.h> #include <stdlib.h> typedef int Myfunc(const char *, const struct stat *, int); static Myfunc myfunc_rename; static int dopath(Myfunc *); static int myftw(char *, Myfunc *); static char *fullpath; // 存储文件完整路径 static char *target_filename; // 要查找并重命名的目标文件名 static int rename_count = 0; // 成功重命名的文件数 // 文件类型标记 #define FTW_F 1 /* 普通文件 */ #define FTW_D 2 /* 目录 */ #define FTW_DNR 3 /* 不可读目录 */ #define FTW_NS 4 /* 无法stat的文件 */ int main(int argc, char *argv[]) { int ret; // 校验参数:支持 myfind <指定目录> <要改名的文件名> if (argc != 3) { err_quit("usage: myfind <target_directory> <filename_to_rename>"); } target_filename = argv[2]; rename_count = 0; ret = myftw(argv[1], myfunc_rename); if (rename_count == 0) { printf("未找到名为 '%s' 的文件,无需重命名\n", target_filename); } else { printf("成功将 %d 个文件重命名为 'pass'\n", rename_count); } exit(ret); } static int myftw(char *pathname, Myfunc *func) { size_t len; fullpath = path_alloc(&len); // 从apue库获取路径缓冲区 strncpy(fullpath, pathname, len); fullpath[len-1] = 0; // 确保字符串终止 return(dopath(func)); } static int dopath(Myfunc *func) { struct stat statbuf; struct dirent *dirp; DIR *dp; int ret; char *ptr; // 获取文件属性失败 if (lstat(fullpath, &statbuf) < 0) return(func(fullpath, &statbuf, FTW_NS)); // 如果是普通文件,执行重命名逻辑 if (S_ISDIR(statbuf.st_mode) == 0) return(func(fullpath, &statbuf, FTW_F)); // 如果是目录,先执行回调(无实际操作) if ((ret = func(fullpath, &statbuf, FTW_D)) != 0) return(ret); // 拼接子目录路径 ptr = fullpath + strlen(fullpath); *ptr++ = '/'; *ptr = 0; // 打开目录失败 if ((dp = opendir(fullpath)) == NULL) return(func(fullpath, &statbuf, FTW_DNR)); // 遍历目录下的所有文件/子目录 while ((dirp = readdir(dp)) != NULL) { // 跳过.和.. if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0) continue; // 拼接子文件路径 strcpy(ptr, dirp->d_name); // 递归处理子文件/子目录 if ((ret = dopath(func)) != 0) break; } // 恢复路径(移除最后拼接的子文件名) ptr[-1] = 0; // 关闭目录 if (closedir(dp) < 0) err_ret("无法关闭目录: %s", fullpath); return(ret); } // 查找目标文件并将其重命名为pass static int myfunc_rename(const char *pathname, const struct stat *statptr, int type) { // 仅处理普通文件 if (type != FTW_F) return 0; // 提取文件名(路径最后一个/后的部分) char *filename = strrchr(pathname, '/'); if (filename == NULL) { filename = (char *)pathname; // 无/,直接是文件名 } else { filename++; // 跳过/,指向实际文件名 } // 匹配到目标文件,执行重命名 if (strcmp(filename, target_filename) == 0) { // 拼接新路径:原目录 + /pass char new_path[PATH_MAX]; strncpy(new_path, pathname, strrchr(pathname, '/') - pathname + 1); strcat(new_path, "pass"); // 执行重命名 if (rename(pathname, new_path) == 0) { printf("成功重命名: %s -> %s\n", pathname, new_path); rename_count++; } else { err_ret("重命名失败: %s", pathname); } } return 0; } UNIX系统中路径的操作与修改 这个程序实现了在指定目录下查找并重命名特定文件的功能,展示了多种路径操作技术。 ...