Comprobación de si existen subcarpetas Linux
Pregunta
Estoy tratando de verificar si una carpeta tiene subcarpetas sin iterar a través de sus hijos, en Linux. Lo más cercano que he encontrado hasta ahora está usando ftw
y detenerse en la primera subcarpeta, o usar scandir
y filtrarse a través de los resultados. Sin embargo, ambos son una exageración para mis propósitos, simplemente quiero un sí/no.
En Windows, esto se hace llamando SHGetFileInfo
y luego probando dwAttributes & SFGAO_HASSUBFOLDER
en la estructura devuelta. ¿Hay tal opción en Linux?
Solución
La respuesta estándar es llamar estadística En el directorio, luego verifique el campo ST_NLINK ("Número de enlaces duros"). En un sistema de archivos estándar, se garantiza que cada directorio tenga 2 enlaces duros (.
y el enlace del directorio principal al directorio actual), por lo que cada enlace duro más allá de 2 indica un subdirectorio (específicamente, el subdirectorio ..
enlace al directorio actual).
Sin embargo, tengo entendido que los sistemas de archivos no son necesarios para implementar esto (ver, por ejemplo, Esta publicación de lista de correo), por lo que no se garantiza que funcione.
De lo contrario, tienes que hacer lo que estás haciendo:
- Iterar sobre el contenido del directorio utilizando parar con la GNU específica
GLOB_ONLYDIR
bandera, o escandir, o readdir. - Llamar estadística en cada resultado y verificar
S_ISDIR(s.st_mode)
Para verificar que los archivos se encuentran son directorios. O, de manera inalcanzable, verifiquestruct dirent.d_type
: si esDT_DIR
Entonces es un archivo, y si esDT_UNKNOWN
, tendrás que estadificarlo después de todo.
Otros consejos
Las posibilidades que ha mencionado (así como las de E.James) me parecen ser más adecuadas para un script de shell que un programa C ++. Suponiendo que la etiqueta "C ++" fue intencional, creo que probablemente estarías mejor usando la API POSIX directamente:
// warning: untested code.
bool has_subdir(char const *dir) {
std::string dot("."), dotdot("..");
bool found_subdir = false;
DIR *directory;
if (NULL == (directory = opendir(dir)))
return false;
struct dirent *entry;
while (!found_subdir && ((entry = readdir(directory)) != NULL)) {
if (entry->d_name != dot && entry->d_name != dotdot) {
struct stat status;
stat(entry->d_name, &status);
found_subdir = S_ISDIR(status.st_mode);
}
}
closedir(directory);
return found_subdir;
}
Lo hace getdirentries ¿Quieres que quieras que haga? Creo que no devuelve nada si no hay directorios. Hubiera probado esto yo mismo, pero estoy temporalmente sin acceso a una caja de Linux :(