Use a função opendir em C

Jinku Hu 12 outubro 2023
  1. Use a função opendir para abrir um fluxo de diretório
  2. Use a função readdir para iterar as entradas do diretório
Use a função opendir em C

Este artigo irá explicar vários métodos de como usar a função opendir em C.

Use a função opendir para abrir um fluxo de diretório

A função opendir é parte da especificação POSIX e é definida no arquivo de cabeçalho <dirent.h>. A função usa um único argumento de ponteiro char para especificar o nome do diretório a ser aberto. opendir devolve a estrutura DIR* ou NULL se for encontrado um erro. O tipo de dados DIR é implementado para representar o fluxo de diretório, mas o usuário não deve alocar objetos do tipo DIR. No código de exemplo a seguir, pegamos o nome do diretório do primeiro argumento da linha de comando e passamos o valor para a função opendir.

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

int main(int argc, char *argv[]) {
  DIR *dp;
  struct dirent *dirp;

  if (argc != 2) {
    fprintf(stderr, "Usage: ./program directory_name\n");
    exit(EXIT_FAILURE);
  }

  dp = opendir(argv[1]);

  while ((dirp = readdir(dp)) != NULL) printf("%s\n", dirp->d_name);

  closedir(dp);
  exit(EXIT_SUCCESS);
}

Use a função readdir para iterar as entradas do diretório

Uma vez que o fluxo de diretório é aberto e recuperamos o DIR* válido, podemos ler cada entrada nele usando a função readdir. Cada chamada para a função readdir retorna um ponteiro para a estrutura dirent que representa a próxima entrada do diretório. Quando o fim do fluxo de diretório é alcançado, readdir retorna NULL. Assim, implementamos um loop while simples que imprime cada entrada no fluxo de diretório aberto. Modificamos o código em torno das chamadas de função opendir e closedir para verificar se há erros e gerar a mensagem correspondente para depuração. É sempre uma prática boa e segura verificar se as funções da biblioteca foram retornadas com êxito.

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

int main(int argc, char *argv[]) {
  DIR *dp;
  struct dirent *dirp;

  if (argc != 2) {
    fprintf(stderr, "Usage: ./program directory_name\n");
    exit(EXIT_FAILURE);
  }

  errno = 0;
  if ((dp = opendir(argv[1])) == NULL) {
    switch (errno) {
      case EACCES:
        printf("Permission denied\n");
        break;
      case ENOENT:
        printf("Directory does not exist\n");
        break;
      case ENOTDIR:
        printf("'%s' is not a directory\n", argv[1]);
        break;
    }
    exit(EXIT_FAILURE);
  }

  while ((dirp = readdir(dp)) != NULL) printf("%s\n", dirp->d_name);

  if (closedir(dp) == -1) perror("closedir");

  exit(EXIT_SUCCESS);
}

Como alternativa, podemos adicionar algumas instruções condicionais de verificação de erro para a função readdir porque o exemplo anterior pode produzir uma saída pouco clara quando o nome do diretório é inválido ou ocorreu um erro diferente. O código a seguir produzirá adicionalmente o status de fim do diretório atingido após a iteração bem-sucedida.

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

int main(int argc, char *argv[]) {
  DIR *dp;
  struct dirent *dirp;

  if (argc != 2) {
    fprintf(stderr, "Usage: ./program directory_name\n");
    exit(EXIT_FAILURE);
  }

  errno = 0;
  if ((dp = opendir(argv[1])) == NULL) {
    switch (errno) {
      case EACCES:
        printf("Permission denied\n");
        break;
      case ENOENT:
        printf("Directory does not exist\n");
        break;
      case ENOTDIR:
        printf("'%s' is not a directory\n", argv[1]);
        break;
    }
    exit(EXIT_FAILURE);
  }

  errno = 0;
  while ((dirp = readdir(dp)) != NULL) printf("%s\n", dirp->d_name);

  if (errno != 0) {
    if (errno == EBADF)
      printf("Invalid directory stream descriptor\n");
    else
      perror("readdir");
  } else {
    printf("End-of-directory reached\n");
  }

  if (closedir(dp) == -1) perror("closedir");

  exit(EXIT_SUCCESS);
}
Autor: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

Artigo relacionado - C File