You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用POSIX系统调用实现多文件重复复制至指定目录

基于POSIX系统调用实现多文件复制工具

需求说明

  • 实现命令行复制工具,仅使用POSIX标准系统调用完成操作
  • 支持传入多个源文件路径(允许重复指定同一文件),最后一个参数固定为目标目录
  • 将每个源文件复制到目标目录下,保持原文件名不变

测试环境准备

运行以下Shell脚本创建测试目录和文件:

setup () {
    mkdir -p t/a t/b
    echo "XXXX" > t/a/a
    echo "XXXX" > t/b/a
    echo "MMMM" > t/a/b
}
setup

实现思路

核心依赖POSIX标准系统调用完成文件操作,流程如下:

  1. 参数校验:确保命令行参数数量≥2,且最后一个参数为合法目录
  2. 遍历所有源文件(除最后一个参数外的所有参数):
    • 用stat检查源文件是否为常规文件
    • 用open以只读模式打开源文件
    • 构造目标文件路径:目标目录 + 源文件的基础文件名(通过basename获取)
    • 用open以「只写+创建+截断」模式打开目标文件,继承源文件权限
    • 循环调用read读取源文件内容到缓冲区,再用write写入目标文件,直到读取完毕
    • 关闭源文件和目标文件描述符
  3. 错误处理:对每个系统调用返回值做检查,出现错误时用perror打印信息并继续处理下一个文件

完整代码实现

基于给定的起始代码补全如下:

#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include <libgen.h>
#include <string.h>
#define BS 512

int main(int argc, char *argv[]) {
    // 校验参数数量
    if (argc < 2) {
        fprintf(stderr, "用法: %s <源文件1> [源文件2...] <目标目录>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    // 处理目标目录:最后一个参数
    char *dest_dir = argv[argc - 1];
    struct stat dest_stat;
    if (stat(dest_dir, &dest_stat) == -1 || !S_ISDIR(dest_stat.st_mode)) {
        fprintf(stderr, "错误: %s 不是合法目录\n", dest_dir);
        exit(EXIT_FAILURE);
    }

    // 遍历所有源文件
    for (int i = 1; i < argc - 1; i++) {
        char *src_path = argv[i];
        struct stat src_stat;

        // 检查源文件是否为常规文件
        if (stat(src_path, &src_stat) == -1) {
            perror(src_path);
            continue;
        }
        if (!S_ISREG(src_stat.st_mode)) {
            fprintf(stderr, "%s 不是常规文件,跳过\n", src_path);
            continue;
        }

        // 打开源文件
        int src_fd = open(src_path, O_RDONLY);
        if (src_fd == -1) {
            perror(src_path);
            continue;
        }

        // 构造目标文件路径
        char *src_basename = basename(src_path);
        char dest_path[1024];
        snprintf(dest_path, sizeof(dest_path), "%s/%s", dest_dir, src_basename);

        // 打开目标文件
        int dest_fd = open(dest_path, O_WRONLY | O_CREAT | O_TRUNC, src_stat.st_mode);
        if (dest_fd == -1) {
            perror(dest_path);
            close(src_fd);
            continue;
        }

        // 循环读写数据
        ssize_t bytes_read;
        char buf[BS];
        while ((bytes_read = read(src_fd, buf, BS)) > 0) {
            if (write(dest_fd, buf, bytes_read) != bytes_read) {
                perror(dest_path);
                close(src_fd);
                close(dest_fd);
                goto next_file;
            }
        }

        if (bytes_read == -1) {
            perror(src_path);
        }

        // 关闭文件描述符
        close(src_fd);
        close(dest_fd);

next_file:
        continue;
    }

    return EXIT_SUCCESS;
}

编译与测试

  1. 编译代码:
gcc copy.c -o copy
  1. 运行示例命令:
# 示例1:重复复制t/a/a两次,复制t/a/b一次到t/b/
./copy t/a/a t/a/a t/a/b t/b/
# 示例2:重复复制t/a/b三次,复制t/a/a一次到t/b/
./copy t/a/a t/a/b t/a/b t/a/b t/b/
  1. 验证结果:
# 查看目标目录文件
ls t/b/
# 检查文件内容
cat t/b/a t/b/b

内容的提问来源于stack exchange,提问作者CopX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 20:30:50