En la programación del sistema Linux, a menudo es necesario recorrer el directorio para obtener todos los archivos y subdirectorios del directorio. Atravesar directorios de forma recursiva es un método común que se puede implementar utilizando el lenguaje C. Este blog presentará en detalle cómo usar el lenguaje C para implementar el proceso de recorrer directorios de forma recursiva, brindar ejemplos de código correspondientes y explicar el uso de funciones relacionadas.
Directorio de artículos
1. Introducción de funciones relacionadas
1.1 abrirdir()
1.1.1 Prototipo de función, parámetros y valor de retorno
opendir
La función se usa para abrir un directorio y devolver un DIR
puntero al tipo, que se usa para operaciones de directorio posteriores.
prototipo:
DIR *opendir(const char *path);
parámetro:
path
: Ruta al directorio a abrir.
valor de retorno:
- Valor de retorno: si el directorio se abre con éxito, se devuelve un
DIR
puntero al tipo ; si falla, se devuelveNULL
.
1.1.2 Ejemplo de función
Aquí hay un ejemplo del uso opendir
de una función para abrir un directorio:
#include <stdio.h>
#include <dirent.h>
int main() {
const char *path = "/path/to/directory";
DIR *dir = opendir(path);
if (dir == NULL) {
perror("opendir");
return -1;
}
// 目录操作...
closedir(dir);
return 0;
}
1.1.3 Código Explicación
En el ejemplo anterior, primero definimos la ruta del directorio para abrir path
, luego usamos opendir
la función para abrir el directorio y almacenamos el puntero devuelto en dir
una variable. Luego, podemos realizar algunas operaciones de directorio, como usar readdir
funciones para leer archivos en el directorio. Finalmente, usamos closedir
la función para cerrar el directorio.
Si opendir
la función falla, regresa NULL
y almacena el mensaje de error en una variable global errno
. Podemos usar perror
la función para imprimir mensajes de error para depurar y solucionar problemas
Cabe señalar que después de usar DIR
el puntero del tipo, debe recordar usar closedir
la función para cerrar el directorio para liberar recursos relacionados.
1.2 readdir()
1.2.1 Prototipo de función, parámetro, valor de retorno y definición de estructura
readdir
La función se usa para leer los archivos en el directorio y devuelve un dirent
puntero a la estructura.
prototipo:
struct dirent *readdir(DIR *dir);
parámetro:
dir
: Un puntero al directorio abierto.
valor de retorno:
- Valor devuelto: si el siguiente archivo se lee con éxito,
dirent
se devuelve un puntero a la estructura; si se llega al final del directorio o se produce un error, se devuelveNULL
.
dirent
La estructura se define de la siguiente manera:
struct dirent {
ino_t d_ino; // 文件的inode号
off_t d_off; // 文件在目录中的偏移量
unsigned short d_reclen; // 文件名的长度
unsigned char d_type; // 文件的类型
char d_name[256]; // 文件名
};
1.2.2 Ejemplos de funciones
Aquí hay un readdir
ejemplo del uso de una función para leer un archivo en un directorio:
#include <stdio.h>
#include <dirent.h>
int main() {
const char *path = "/path/to/directory";
DIR *dir = opendir(path);
if (dir == NULL) {
perror("opendir");
return -1;
}
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
printf("%s\n", entry->d_name);
}
closedir(dir);
return 0;
}
1.2.3 Código Explicación
En el ejemplo anterior, primero usamos opendir
la función para abrir el directorio y almacenar el puntero devuelto en dir
una variable. Luego, usamos un bucle para leer cada archivo en el directorio. readdir
La función devolverá un dirent
puntero a la estructura, podemos d_name
obtener el nombre del archivo accediendo a los miembros y realizar las operaciones correspondientes. En el ejemplo, simplemente usamos printf
la función para imprimir el nombre del archivo. Finalmente, usamos closedir
la función para cerrar el directorio.
Cabe señalar que cuando readdir
la función devuelve NULL
, significa que se ha leído el final del directorio o se ha producido un error. Por lo tanto, podemos NULL
determinar si continuar leyendo los archivos en el directorio juzgando si el valor devuelto es .
1.3 cerradoir()
1.3.1 Prototipo de función, parámetros y valor de retorno
closedir
La función se usa para cerrar el directorio abierto por la función antes opendir
y liberar recursos relacionados.
prototipo:
int closedir(DIR *dir);
parámetro:
dir
: Un puntero al directorio abierto.
valor de retorno:
- Valor devuelto: 0 si el directorio se cerró correctamente o -1 si se produjo un error.
1.3.2 Ejemplo de función
Aquí hay un ejemplo del uso de una closedir
función para cerrar un directorio:
#include <stdio.h>
#include <dirent.h>
int main() {
const char *path = "/path/to/directory";
DIR *dir = opendir(path);
if (dir == NULL) {
perror("opendir");
return -1;
}
// 目录操作...
if (closedir(dir) == -1) {
perror("closedir");
return -1;
}
return 0;
}
1.3.3 Código Explicación
En el ejemplo anterior, primero usamos opendir
la función para abrir el directorio y almacenar el puntero devuelto en dir
una variable. A continuación, podemos hacer algo de manipulación de directorios. Finalmente, usamos closedir
la función para cerrar el directorio y verificar si el valor de retorno es -1 para ver si ocurrió un error.
Cabe señalar que closedir
la función liberará recursos relacionados con el directorio, por lo que después de usar el directorio, debe recordar llamar a la closedir
función para cerrar el directorio.
1.4 snprintf()
1.4.1 Prototipo de función, parámetros y valor de retorno
snprintf
La función es una función de formato de cadena segura para generar datos formateados en una cadena.
prototipo:
int snprintf(char *str, size_t size, const char *format, ...);
parámetro:
str
: Puntero a la cadena utilizada para almacenar el resultado formateado.size
: El tamaño de la cadena que almacena el resultado formateado.format
: cadena de formato, especifique el formato de salida.
valor de retorno:
- Valor devuelto: Devuelve el número de caracteres escritos en la cadena (sin incluir el terminador) en caso de éxito o un valor negativo en caso de error.
snprintf
funciona printf
como una función, pero almacena el resultado formateado en la cadena especificada en lugar de enviarlo a la salida estándar.
1.4.2 Ejemplo de función
Aquí hay un snprintf
ejemplo usando la función:
#include <stdio.h>
int main() {
char buffer[100];
int num = 42;
const char *str = "Hello, world!";
int len = snprintf(buffer, sizeof(buffer), "Number: %d, String: %s", num, str);
if (len >= sizeof(buffer)) {
printf("Buffer is too small\n");
return -1;
}
printf("Formatted string: %s\n", buffer);
return 0;
}
1.4.3 Código Explicación
En el ejemplo anterior, primero definimos una matriz de caracteres de tamaño 100 buffer
para almacenar el resultado formateado. Luego, definimos una variable entera num
y una variable de cadena str
para pasar a la cadena de formato. A continuación, usamos snprintf
la función para almacenar el resultado formateado buffer
y enviarlo a la salida estándar. Finalmente, verificamos len
si el valor devuelto excede buffer
el tamaño de para ver si el búfer es lo suficientemente grande para contener el resultado formateado.
Cabe señalar que snprintf
la función se formateará de acuerdo con la cadena de formato y los parámetros especificados, y almacenará el resultado en la cadena especificada. Garantiza que el resultado formateado no exceda el tamaño especificado y trunca automáticamente la cadena si es necesario. Por lo tanto, el uso snprintf
de funciones puede evitar el problema del desbordamiento del búfer.
1.5 strcmp()
1.5.1 Prototipo de función, parámetros y valor de retorno
strcmp
Función para comparar dos cadenas para la igualdad.
prototipo:
int strcmp(const char *s1, const char *s2);
parámetro:
s1
: La primera cadena a comparar.s2
: La segunda cadena a comparar.
valor de retorno:
- Valor devuelto: Devuelve 0 si las dos cadenas son iguales; devuelve un número negativo si la primera cadena es menor que la segunda; devuelve un número positivo si la primera cadena es mayor que la segunda.
strcmp
La función compara las dos cadenas carácter por carácter, lexicográficamente, hasta que se encuentra un carácter desigual o se encuentra el final de la cadena\0
. Devuelve 0 si las dos cadenas son iguales; devuelve un número negativo si la primera cadena es lexicográficamente anterior a la segunda; devuelve un número negativo si la primera cadena es lexicográficamente segunda Después de la cadena, se devuelve un número positivo.
1.5.2 Ejemplos de funciones
Aquí hay un strcmp
ejemplo que usa una función para comparar dos cadenas:
#include <stdio.h>
#include <string.h>
int main() {
const char *s1 = "Hello";
const char *s2 = "World";
int result = strcmp(s1, s2);
if (result == 0) {
printf("The strings are equal\n");
} else if (result < 0) {
printf("The first string is less than the second string\n");
} else {
printf("The first string is greater than the second string\n");
}
return 0;
}
1.5.3 Código Explicación
En el ejemplo anterior, definimos dos cadenas s1
y s2
luego usamos strcmp
la función para compararlas. Dependiendo del valor de retorno, mostramos el resultado correspondiente.
Cabe señalar que strcmp
la función compara el contenido de las cadenas, no las direcciones de las cadenas. Por lo tanto, incluso si las direcciones de las dos cadenas son diferentes, siempre que su contenido sea el mismo, strcmp
la función devolverá 0. Además, strcmp
las funciones distinguen entre mayúsculas y minúsculas, y si desea comparaciones que no distingan entre mayúsculas y minúsculas, puede usar strcasecmp
funciones.
2. Implementación de directorio transversal recursivo
2.1 Código de ejemplo:
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>
void traverse_directory(const char *path) {
DIR *dir;
struct dirent *entry;
struct stat file_stat;
// 打开目录
dir = opendir(path);
if (dir == NULL) {
perror("opendir");
return;
}
// 读取目录中的每个文件
while ((entry = readdir(dir)) != NULL) {
// 构建文件的完整路径
char file_path[1024];
snprintf(file_path, sizeof(file_path), "%s/%s", path, entry->d_name);
// 获取文件的信息
if (lstat(file_path, &file_stat) < 0) {
perror("lstat");
continue;
}
// 判断文件类型
if (S_ISDIR(file_stat.st_mode)) {
// 如果是目录,则递归遍历
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
traverse_directory(file_path);
} else {
// 如果是文件,则打印文件名
printf("%s\n", file_path);
}
}
// 关闭目录
closedir(dir);
}
int main(int argc,char *argv[]) {
traverse_directory(argv[]);
return 0;
}
2.2 Explicación del código
En el código anterior, definimos una traverse_directory
función para recorrer directorios recursivamente. Esta función toma una ruta como argumento, primero abre el directorio y luego lee cada archivo en el directorio. Para cada archivo, primero construimos la ruta completa al archivo, luego usamos lstat
una función para obtener la información del archivo. Si el archivo es un directorio, la función se llama recursivamente traverse_directory
; si el archivo es un archivo normal, se imprime el nombre del archivo. Finalmente, cerramos el directorio.
En main
la función, especificamos la ruta del directorio a recorrer y llamamos traverse_directory
a la función a recorrer.
dirent.h
Cabe señalar que en el código anterior, los archivos de encabezado se usan sys/stat.h
para operar directorios y archivos, y los archivos stdio.h
de encabezado string.h
se usan para realizar operaciones de cadena. Además, las funciones se usan en el código lstat
para obtener información sobre archivos en lugar de stat
funciones porque lstat
las funciones pueden manejar enlaces simbólicos.