C语言实现伪Shell的cp命令:如何处理目标为文件或目录?
C语言伪Shell中cp命令适配目标路径的修改方案
问题背景
当前实现的copyFile函数仅支持目标路径为文件名的场景,需要修改以适配三种目标形式:
file:直接将源文件复制为指定文件名dir/file:将源文件复制到指定目录下的指定文件名dir:将源文件复制到指定目录,保留原文件名
修改步骤
1. 添加目录判断逻辑
使用stat函数获取目标路径的文件状态,判断其是否为目录。如果目标路径存在且是目录,需构造新的目标路径(目录+源文件名)。
2. 构造最终目标路径
利用basename函数提取源文件的文件名,拼接在目录路径后形成完整目标路径,自动处理路径末尾是否带/的情况,避免出现dir//file格式错误。
3. 修复原代码缓冲区错误
原代码中char* buff[1024]是指针数组,改为char buff[1024]作为字节缓冲区,避免内存访问异常。
4. 优化权限设置
创建目标文件时继承源文件的权限,贴近系统cp命令的默认行为。
修改后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> #include <libgen.h> void copyFile(char *sourcePath, char *destinationPath) { int srcCheck, destCheck, standardCheck; char buff[1024]; // 修复缓冲区类型错误 struct stat srcStat, destStat; char finalDestPath[PATH_MAX]; // 获取源文件信息(用于权限复制) if (stat(sourcePath, &srcStat) < 0) { write(1, "Error getting source file info\n", strlen("Error getting source file info\n")); return; } srcCheck = open(sourcePath, O_RDONLY); if (srcCheck < 0) { write(1, "Error with opening source\n", strlen("Error with opening source\n")); return; } // 判断目标路径是否为目录 if (stat(destinationPath, &destStat) == 0) { if (S_ISDIR(destStat.st_mode)) { // 目标是目录,构造最终路径:目录/源文件名 char *srcBasename = basename(sourcePath); snprintf(finalDestPath, sizeof(finalDestPath), "%s/%s", destinationPath, srcBasename); destinationPath = finalDestPath; } } // 创建/打开目标文件,使用源文件的权限 destCheck = open(destinationPath, O_WRONLY | O_CREAT | O_TRUNC, srcStat.st_mode & 0777); if (destCheck < 0) { close(srcCheck); write(1, "Error opening/creating destination\n", strlen("Error opening/creating destination\n")); return; } // 复制文件内容 while ((standardCheck = read(srcCheck, buff, sizeof(buff))) > 0) { if (write(destCheck, buff, standardCheck) != standardCheck) { write(1, "Error writing to destination\n", strlen("Error writing to destination\n")); close(srcCheck); close(destCheck); return; } } if (standardCheck == -1) { write(1, "Error reading source\n", strlen("Error reading source\n")); } // 关闭文件描述符 if (close(srcCheck) == -1) { write(1, "Error closing source\n", strlen("Error closing source\n")); } if (close(destCheck) == -1) { write(1, "Error closing destination\n", strlen("Error closing destination\n")); } }
关键说明
- 通过
stat判断目标类型,自动处理目录场景下的路径拼接 - 修复缓冲区类型错误,解决潜在的内存访问问题
- 继承源文件权限,保持复制后的文件权限一致性
- 增加写入错误检测,避免部分写入未被捕获的情况
内容的提问来源于stack exchange,提问作者Amy Gregg
相关产品推荐
相关产品推荐

