温馨提示×

Ubuntu系统如何操作copendir

小樊
49
2025-10-06 19:46:25
栏目: 智能运维

Note: The correct function name in Ubuntu/Linux systems is opendir (not “copendir”), which is part of the POSIX standard for opening directories. Below are detailed operations for using opendir and related functions.

1. Include Necessary Headers

To use opendir, you must include the <dirent.h> header (for directory operations) and optionally <stdio.h>, <stdlib.h>, and <errno.h> for error handling and standard I/O.

#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h> // For stat() (used in recursive traversal)

2. Open a Directory with opendir

The opendir function takes a directory path as input and returns a DIR* pointer (representing the directory stream). If it fails (e.g., invalid path or permission issues), it returns NULL and sets errno.

DIR *dir = opendir("/path/to/target_directory");
if (dir == NULL) {
    perror("Error opening directory"); // Prints error message (e.g., "No such file or directory")
    exit(EXIT_FAILURE);
}

3. Read Directory Contents with readdir

Use readdir to iterate through directory entries. Each call returns a struct dirent* containing the entry name (d_name). Skip the special entries "." (current directory) and ".." (parent directory) to avoid recursion issues.

struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
    // Skip "." and ".."
    if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
        continue;
    }
    printf("Entry: %s\n", entry->d_name); // Print entry name
}

4. Close the Directory with closedir

Always close the directory stream after use to free system resources. Check the return value (0 for success, -1 for failure).

if (closedir(dir) == -1) {
    perror("Error closing directory");
    exit(EXIT_FAILURE);
}

5. Complete Example: List Directory Contents

A simple program that lists all files/subdirectories in a given path:

#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <directory_path>\n", argv[0]);
        return EXIT_FAILURE;
    }

    DIR *dir = opendir(argv[1]);
    if (dir == NULL) {
        perror("opendir");
        return EXIT_FAILURE;
    }

    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
        }
        printf("%s\n", entry->d_name);
    }

    if (closedir(dir) == -1) {
        perror("closedir");
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

Compile & Run:

gcc -o list_dir list_dir.c
./list_dir /path/to/target_directory

6. Recursive Directory Traversal (Copy Example)

To recursively copy a directory (including subdirectories and files), extend the above logic with stat (to check file types) and file I/O operations. Below is a simplified version:

#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

void copy_file(const char *src, const char *dest) {
    FILE *src_file = fopen(src, "rb");
    if (!src_file) {
        perror("fopen (src)");
        return;
    }
    FILE *dest_file = fopen(dest, "wb");
    if (!dest_file) {
        perror("fopen (dest)");
        fclose(src_file);
        return;
    }

    char buffer[1024];
    size_t bytes_read;
    while ((bytes_read = fread(buffer, 1, sizeof(buffer), src_file)) > 0) {
        fwrite(buffer, 1, bytes_read, dest_file);
    }

    fclose(src_file);
    fclose(dest_file);
}

void copy_directory(const char *src, const char *dest) {
    DIR *dir = opendir(src);
    if (!dir) {
        perror("opendir");
        return;
    }

    // Create destination directory if it doesn't exist
    struct stat st = {0};
    if (stat(dest, &st) == -1) {
        mkdir(dest, 0755);
    }

    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
        }

        char src_path[1024], dest_path[1024];
        snprintf(src_path, sizeof(src_path), "%s/%s", src, entry->d_name);
        snprintf(dest_path, sizeof(dest_path), "%s/%s", dest, entry->d_name);

        if (stat(src_path, &st) == -1) {
            perror("stat");
            continue;
        }

        if (S_ISDIR(st.st_mode)) {
            copy_directory(src_path, dest_path); // Recurse for directories
        } else {
            copy_file(src_path, dest_path); // Copy files
        }
    }

    closedir(dir);
}

int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <source_directory> <destination_directory>\n", argv[0]);
        return EXIT_FAILURE;
    }

    copy_directory(argv[1], argv[2]);
    printf("Directory copied successfully.\n");
    return EXIT_SUCCESS;
}

Compile & Run:

gcc -o copy_dir copy_dir.c
./copy_dir /path/to/source /path/to/destination

Key Notes

  • Error Handling: Always check return values of opendir, readdir, and closedir. Use perror to print human-readable error messages.
  • Permissions: Ensure you have read access to the source directory and write access to the target directory.
  • Special Entries: Skip "." and ".." to avoid infinite loops during recursion.
  • Symbolic Links: The above examples do not handle symbolic links. Use lstat instead of stat if you need to process them differently.

For actual directory copying, consider using the built-in cp -r command (more efficient and robust) unless you need custom logic.

0