Quiero una forma fácil de crear varios directorios en C ++ / Linux.
Por ejemplo, quiero guardar un archivo lola.file en el directorio:
/tmp/a/b/c
pero si los directorios no están ahí, quiero que se creen automágicamente. Un ejemplo práctico sería perfecto.
Respuestas:
Con C ++ 17 o posterior, existe el encabezado estándar
<filesystem>
con funciónstd::filesystem::create_directories
que debe usarse en los programas modernos de C ++. Sin embargo, las funciones estándar de C ++ no tienen el argumento de permisos explícitos (modo) específicos de POSIX.Sin embargo, aquí hay una función de C que se puede compilar con compiladores de C ++.
Las macros
STRDUP()
yFREE()
son versiones de comprobación de errores destrdup()
yfree()
, declaradas enemalloc.h
(e implementadas enemalloc.c
yestrdup.c
). El"sysstat.h"
encabezado trata con versiones rotas<sys/stat.h>
y puede ser reemplazado por<sys/stat.h>
en sistemas Unix modernos (pero hubo muchos problemas en 1990). Y"mkpath.h"
declaramkpath()
.El cambio entre v1.12 (versión original de la respuesta) y v1.13 (versión enmendada de la respuesta) fue la prueba para
EEXIST
indo_mkdir()
. Esto fue señalado como necesario por Switch , gracias, Switch. El código de prueba se actualizó y reprodujo el problema en una MacBook Pro (Intel Core i7 de 2.3GHz, con Mac OS X 10.7.4) y sugiere que el problema se solucionó en la revisión (pero las pruebas solo pueden mostrar la presencia de errores , nunca su ausencia). El código que se muestra ahora es v1.16; se han realizado cambios cosméticos o administrativos desde v1.13 (como el uso enmkpath.h
lugar dejlss.h
e incluir<unistd.h>
incondicionalmente en el código de prueba únicamente). Es razonable argumentar que"sysstat.h"
debería reemplazarse por a<sys/stat.h>
menos que tenga un sistema inusualmente recalcitrante.(Por la presente, se le otorga permiso para usar este código para cualquier propósito con atribución).
Este código está disponible en mi repositorio SOQ (Preguntas de desbordamiento de pila) en GitHub como archivos
mkpath.c
ymkpath.h
(etc.) en el subdirectorio src / so-0067-5039 .fuente
if (errno != EEXIST) { status = -1; }
cuando mkdir falla.stat()
antesmkdir()
; es un problema TOCTOU (tiempo de comprobación, tiempo de uso). Intenté hacerle cosquillas al error con un script de shell que ejecuta 13 procesos en segundo plano creando la misma ruta de 29 elementos, y no pude encontrarlo. Luego pirateé el programa de prueba para bifurcar 20 veces y hacer que cada niño lo intentara, y eso logró solucionar el error. El código fijo tendráif (mkdir(path, mode) != 0 && errno != EEXIST) status = -1;
. Eso no muestra el error.jlss.h
,emalloc.h
), no bibliotecas. Sin embargo, el código está disponible en mi SOQ (Preguntas desbordamiento de pila) repositorio en GitHub como archivosjlss.h
,emalloc.c
yemalloc.h
en el / libsoq src subdirectorio. Usted necesitaráposixver.h
también, y algunos otros (debug.h
,stderr.c
,stderr.h
- creo que eso es todo, pero lo que necesita debe estar todos en ese directorio).Fácil con Boost.Filesystem:
create_directories
Devuelve:
true
si se creó un nuevo directorio, en caso contrariofalse
.fuente
The <filesystem> header is not part of C++11; it is a proposal for C++ TR2 based on the Boost.Filesystem library. Visual C++ 2012 includes an implementation of the proposed library.
es la forma más corta en la que puedo pensar (en términos de la longitud del código, no necesariamente el tiempo de ejecución).
No es multiplataforma, pero funcionará en Linux.
fuente
De aqui . Puede que tenga que hacer mkdirs separados para / tmp, / tmp / a, / tmp / a / b / y luego / tmp / a / b / c porque no hay un equivalente de la marca -p en la api de C. Asegúrese de ignorar el error EEXISTS mientras realiza los de nivel superior.
fuente
("/tmp/",...)
,("/tmp/a/",...)
,("/tmp/a/b/",...)
,("/tmp/a/b/c/",...)
Aquí está mi ejemplo de código (funciona tanto para Windows como para Linux):
Uso:
fuente
stat
(relacionados con__STDC__
) que no es necesario realizar la prueba del precompilador.Cabe señalar que a partir de la interfaz del sistema de archivos C ++ 17 es parte de la biblioteca estándar. Esto significa que uno puede tener lo siguiente para crear directorios:
Más información aquí: https://en.cppreference.com/w/cpp/filesystem/create_directory
Además, con gcc, es necesario "-std = c ++ 17" para CFLAGS. Y "-lstdc ++ fs" a LDLIBS. Esto último potencialmente no será necesario en el futuro.
fuente
Esto es similar al anterior, pero funciona hacia adelante a través de la cadena en lugar de recursivamente hacia atrás. Deja errno con el valor correcto para la última falla. Si hay una barra inclinada, hay un tiempo extra a través del bucle que podría haberse evitado mediante un find_first_of () fuera del bucle o detectando el / inicial y estableciendo pre en 1. La eficiencia es la misma ya sea que nos configure un primer ciclo o una llamada previa al ciclo, y la complejidad sería (ligeramente) mayor cuando se usa la llamada previa al ciclo.
fuente
Dijiste "C ++" pero todos aquí parecen estar pensando "Bash shell".
Consulte el código fuente de GNU
mkdir
; entonces puede ver cómo implementar los comandos de shell en C ++.fuente
fuente
Así que necesito
mkdirp()
hoy, y encontré las soluciones en esta página demasiado complicadas. Por lo tanto, escribí un fragmento bastante corto, que se puede copiar fácilmente para otros que se encuentren con este hilo y se pregunten por qué necesitamos tantas líneas de código.mkdirp.h
mkdirp.cpp
Si no te gusta la conversión constante y la modificación temporal de la cadena, haz una
strdup()
yfree()
luego.fuente
Dado que esta publicación ocupa un lugar destacado en Google para "Crear árbol de directorios", voy a publicar una respuesta que funcionará para Windows; esto funcionará usando la API Win32 compilada para UNICODE o MBCS. Esto se transfirió del código de Mark anterior.
Dado que estamos trabajando en Windows, los separadores de directorio son barras invertidas, no barras diagonales. Si prefiere tener barras diagonales, cambie
'\\'
a'/'
Funcionará con:
y
(es decir, no necesita barra inclinada final, por lo que no tiene que buscarla).
Antes de decir "Simplemente use SHCreateDirectoryEx () en Windows", tenga en cuenta que SHCreateDirectoryEx () está obsoleto y podría eliminarse en cualquier momento de futuras versiones de Windows.
fuente
c:\this\is\a/mixed/path\of\slashes
Normalmente, las barras diagonales de Windows son barras invertidas. Lo que debería suceder es que la persona que llama debe desinfectar la ruta y asegurarse de que todas las barras sean correctas antes de llamar a este método.Sé que es una pregunta antigua, pero aparece en los primeros lugares de los resultados de búsqueda de Google y las respuestas proporcionadas aquí no están realmente en C ++ o son demasiado complicadas.
Tenga en cuenta que en mi ejemplo createDirTree () es muy simple porque todo el trabajo pesado (verificación de errores, validación de ruta) debe realizarse mediante createDir () de todos modos. También createDir () debería devolver verdadero si el directorio ya existe o todo no funcionará.
Así es como lo haría en C ++:
Por supuesto, la función createDir () será específica del sistema y ya hay suficientes ejemplos en otras respuestas sobre cómo escribirla para Linux, así que decidí omitirla.
fuente
Si dir no existe, créelo:
fuente
Se han descrito muchos enfoques aquí, pero la mayoría de ellos necesitan una codificación dura de su ruta en su código. Existe una solución fácil para ese problema, utilizando QDir y QFileInfo, dos clases de marco Qt. Dado que ya está en un entorno Linux, debería ser fácil de usar Qt.
Asegúrese de tener acceso de escritura a esa ruta.
fuente
fuente
-p
opción es lo que estoy buscando. ¡Gracias!Aquí está la función recursiva de C / C ++ que se utiliza
dirname()
para recorrer el árbol de directorios de abajo hacia arriba. Se detendrá tan pronto como encuentre un antepasado existente.fuente
Los demás te dieron la respuesta correcta, pero pensé en demostrar otra cosa interesante que puedes hacer:
Creará las siguientes rutas:
Las llaves le permiten crear varios directorios a la vez en el mismo nivel de la jerarquía, mientras que la
-p
opción significa "crear directorios principales según sea necesario".fuente