¿Cómo obtengo el directorio desde el que se ejecuta un progtwig?

¿Existe un método independiente de la plataforma y de sistema de archivos para obtener la ruta completa del directorio desde donde se ejecuta un progtwig utilizando C / C ++? No debe confundirse con el directorio de trabajo actual. (No sugiera bibliotecas a menos que sean estándares como clib o STL).

(Si no hay un método independiente de plataforma / sistema de archivos, también son bienvenidas las sugerencias que funcionan en Windows y Linux para sistemas de archivos específicos).

    Aquí hay un código para obtener la ruta completa a la aplicación de ejecución:

    Windows:

     int bytes = GetModuleFileName(NULL, pBuf, len); if(bytes == 0) return -1; else return bytes; 

    Linux:

     char szTmp[32]; sprintf(szTmp, "/proc/%d/exe", getpid()); int bytes = MIN(readlink(szTmp, pBuf, len), len - 1); if(bytes >= 0) pBuf[bytes] = '\0'; return bytes; 

    Si busca el directorio actual cuando su progtwig se inicia por primera vez, entonces efectivamente tiene el directorio desde el que comenzó su progtwig. Almacene el valor en una variable y consúltelo más adelante en su progtwig. Esto es distinto del directorio que contiene el archivo de progtwig ejecutable actual . No es necesariamente el mismo directorio; si alguien ejecuta el progtwig desde un símbolo del sistema, entonces el progtwig se ejecuta desde el directorio de trabajo actual del símbolo del sistema, aunque el archivo del progtwig se encuentre en otro lugar.

    getcwd es una función POSIX y es compatible con todas las plataformas compatibles con POSIX. No tendría que hacer nada especial (aparte de inclinar los encabezados derechos unistd.h en Unix y direct.h en windows).

    Como está creando un progtwig C, se vinculará con la biblioteca predeterminada de tiempo de ejecución c, a la que están vinculados TODOS los procesos del sistema (se evitan excepciones especialmente diseñadas) e incluirá esta función de manera predeterminada. El CRT nunca se considera una biblioteca externa porque proporciona la interfaz estándar compatible con el sistema operativo.

    En Windows, la función getcwd ha quedado en desuso en favor de _getcwd. Creo que podrías usarlo de esta manera.

     #include  /* defines FILENAME_MAX */ #ifdef WINDOWS #include  #define GetCurrentDir _getcwd #else #include  #define GetCurrentDir getcwd #endif char cCurrentPath[FILENAME_MAX]; if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))) { return errno; } cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */ printf ("The current working directory is %s", cCurrentPath); 

    Esto es del foro cplusplus

    En windows:

     #include  #include  std::string getexepath() { char result[ MAX_PATH ]; return std::string( result, GetModuleFileName( NULL, result, MAX_PATH ) ); } 

    En Linux:

     #include  #include  #include  std::string getexepath() { char result[ PATH_MAX ]; ssize_t count = readlink( "/proc/self/exe", result, PATH_MAX ); return std::string( result, (count > 0) ? count : 0 ); } 

    En HP-UX:

     #include  #include  #define _PSTAT64 #include  #include  #include  std::string getexepath() { char result[ PATH_MAX ]; struct pst_status ps; if (pstat_getproc( &ps, sizeof( ps ), 0, getpid() ) < 0) return std::string(); if (pstat_getpathname( result, PATH_MAX, &ps.pst_fid_text ) < 0) return std::string(); return std::string( result ); } 

    Si desea una forma estándar sin bibliotecas: No. El concepto completo de un directorio no está incluido en el estándar.

    Si acepta que alguna dependencia (portátil) de una lib casi estándar está bien: use la biblioteca del sistema de archivos de Boost y solicite la ruta_inicial () .

    En mi humilde opinión, es lo más cercano que se puede llegar, con buen karma (Boost es un conjunto de bibliotecas de alta calidad bien establecido)

    Filesystem TS ahora es un estándar (y es compatible con gcc 5.3+ y clang 3.9+), por lo que puedes usar la función current_path() desde él:

     std::string path = std::experimental::filesystem::current_path(); 

    En gcc (5.3+) para incluir el Sistema de archivos, necesita usar:

     #include  

    y vincula tu código con la bandera -lstdc++fs .

    Si desea usar el Sistema de archivos con Microsoft Visual Studio, entonces lea esto .

    Sé que es muy tarde para dar una respuesta en este caso, pero descubrí que ninguna de las respuestas fue tan útil para mí como mi propia solución. Una forma muy simple de obtener la ruta desde su CWD a su carpeta bin es así:

     int main(int argc, char* argv[]) { std::string argv_str(argv[0]); std::string base = argv_str.substr(0, argv_str.find_last_of("/")); } 

    Ahora puede usar esto como una base para su ruta relativa. Entonces, por ejemplo, tengo esta estructura de directorio:

     main ----> test ----> src ----> bin 

    y quiero comstackr mi código fuente para bin y escribir un log para probar Puedo agregar esta línea a mi código.

     std::string pathToWrite = base + "/../test/test.log"; 

    He intentado este enfoque en Linux usando ruta completa, alias, etc. y funciona muy bien.

    NOTA:

    Si está en Windows, debe usar un ‘\’ como separador de archivos no ‘/’. Deberás escapar de esto también, por ejemplo:

     std::string base = argv[0].substr(0, argv[0].find_last_of("\\")); 

    Creo que esto debería funcionar, pero no lo he probado, por lo que los comentarios serían apreciados si funciona o si no funciona.

    No, no hay una forma estándar. Creo que los estándares C / C ++ ni siquiera consideran la existencia de directorios (u otras organizaciones del sistema de archivos).

    En Windows, GetModuleFileName () devolverá la ruta completa al archivo ejecutable del proceso actual cuando el parámetro hModule esté establecido en NULL . No puedo ayudar con Linux.

    También debe aclarar si desea el directorio actual o el directorio donde reside la imagen del progtwig / ejecutable. Tal como está, su pregunta es un poco ambigua en este punto.

    ¿Tal vez concatenar el directorio de trabajo actual con argv [0]? No estoy seguro de si eso funcionaría en Windows, pero funciona en Linux.

    Por ejemplo:

     #include  #include  #include  int main(int argc, char **argv) { char the_path[256]; getcwd(the_path, 255); strcat(the_path, "/"); strcat(the_path, argv[0]); printf("%s\n", the_path); return 0; } 

    Cuando se ejecuta, produce:

    jeremy @ jeremy-desktop: ~ / Desktop $ ./test
    /home/jeremy/Desktop/./test

    No puede usar argv [0] para ese propósito, generalmente contiene una ruta completa al ejecutable, pero no necesariamente, el proceso podría crearse con un valor arbitrario en el campo.

    También, el directorio actual y el directorio con el ejecutable son dos cosas diferentes, por lo que getcwd () tampoco te ayudará.

    En Windows use GetModuleFileName () en los archivos de lectura / dev / proc / procID / .. de Linux .

    Para Win32 GetCurrentDirectory debería hacer el truco.

    Para el sistema Windows en la consola, puede usar el comando system ( dir ). Y la consola le brinda información sobre el directorio, etc. Lea sobre el comando dir en cmd . Pero para los sistemas tipo Unix, no sé … Si se ejecuta este comando, lea el comando bash. ls no muestra el directorio …

    Ejemplo:

     int main() { system("dir"); system("pause"); //this wait for Enter-key-press; return 0; } 

    Solo para astackrlo tardíamente aquí, …

    no existe una solución estándar, ya que los idiomas son independientes de los sistemas de archivos subyacentes, por lo que, como otros han dicho, el concepto de un sistema de archivos basado en directorios está fuera del scope de los lenguajes c / c ++.

    Además, no desea el directorio de trabajo actual, sino el directorio en el que se ejecuta el progtwig, que debe tener en cuenta cómo llegó el progtwig a su ubicación, es decir, se generó como un nuevo proceso mediante un tenedor, etc. Para obtener el directorio en el que se está ejecutando un progtwig, como las soluciones lo han demostrado, se requiere que obtenga esa información de las estructuras de control de proceso del sistema operativo en cuestión, que es la única autoridad en esta cuestión. Por lo tanto, por definición, es una solución específica del sistema operativo.

    En Windows, la forma más sencilla es usar la función _get_pgmptr en stdlib.h para obtener un puntero a una cadena que representa la ruta absoluta al ejecutable, incluido el nombre de los ejecutables.

     char* path; _get_pgmptr(&path); printf(path); // Example output: C:/Projects/Hello/World.exe 
     #include  using namespace std; // The directory path returned by native GetCurrentDirectory() no end backslash string getCurrentDirectoryOnWindows() { const unsigned long maxDir = 260; char currentDir[maxDir]; GetCurrentDirectory(maxDir, currentDir); return string(currentDir); } 

    El comando linux bash que progname informará una ruta al progtwig.

    Incluso si uno pudiera emitir el comando dentro de su progtwig y dirigir el resultado a un archivo tmp y el progtwig posteriormente lee ese archivo tmp, no le dirá si ese progtwig es el que se está ejecutando. Solo te dice dónde se encuentra un progtwig que tiene ese nombre.

    Lo que se requiere es obtener su número de identificación de proceso y analizar el camino al nombre

    En mi progtwig, quiero saber si el progtwig se ejecutó desde el directorio bin del usuario o desde otro en la ruta o desde / usr / bin. / usr / bin contendría la versión compatible. Mi sensación es que en Linux existe la única solución que es portátil.

    Para rutas relativas, esto es lo que hice. Soy consciente de la edad de esta pregunta, simplemente quiero contribuir con una respuesta más simple que funciona en la mayoría de los casos:

    Digamos que tienes un camino como este:

     "path/to/file/folder" 

    Por alguna razón, los ejecutables creados en Linux en eclipse funcionan bien con esto. Sin embargo, Windows se confunde mucho si se le da un camino como este para trabajar.

    Como se mencionó anteriormente, hay varias maneras de obtener la ruta actual al ejecutable, pero la forma más fácil que encuentro funciona de maravilla, en la mayoría de los casos, es agregar esto al FRENTE de su ruta:

     "./path/to/file/folder" 

    Solo agregue “./” para ordenarlo! 🙂 Entonces puede comenzar a cargar desde el directorio que desee, siempre y cuando esté con el ejecutable mismo.

    EDITAR: Esto no funcionará si intentas ejecutar el ejecutable desde code :: blocks si ese es el entorno de desarrollo que se está utilizando, como por alguna razón, code :: blocks no carga cosas correctamente …: D

    EDIT2: Algunas cosas nuevas que he encontrado es que si especifica una ruta estática como esta en su código (Assuming Example.data es algo que necesita cargar):

     "resources/Example.data" 

    Si luego inicia su aplicación desde el directorio real (o en Windows, crea un acceso directo y establece el directorio de trabajo en su directorio de aplicación) entonces funcionará de esa manera. Tenga esto en cuenta al depurar problemas relacionados con las rutas de recursos / archivos faltantes. (Especialmente en IDE que configuran el directorio de trabajo incorrecto al ejecutar un exe de comstackción desde el IDE)

    En plataformas POSIX, puede usar getcwd () .

    En Windows, puede usar _getcwd () , ya que el uso de getcwd () ha quedado en desuso.

    Para las bibliotecas estándar, si Boost fuera lo suficientemente estándar para usted, habría sugerido Boost :: filesystem, pero parece que han eliminado la normalización de ruta de la propuesta. Puede que tenga que esperar hasta que TR2 esté disponible para una solución completamente estándar.

    La initial_path() Boost Filesystem initial_path() comporta como initial_path() POSIX, y tampoco hace lo que quiere por sí misma, pero si lo hace, añada argv[0] a cualquiera de ellos.

    Puede notar que el resultado no siempre es bonito: puede obtener cosas como /foo/bar/../../baz/a.out o /foo/bar//baz/a.out , pero creo que siempre da como resultado una ruta válida que nombra el ejecutable (tenga en cuenta que las barras consecutivas en una ruta se colapsan en una).

    Anteriormente escribí una solución usando envp (el tercer argumento para main() que funcionaba en Linux pero no parecía viable en Windows, así que básicamente estoy recomendando la misma solución que otra persona anteriormente, pero con la explicación adicional de por qué en realidad es correcto incluso si los resultados no son bonitos.

    Como mencionó Minok , no existe tal funcionalidad especificada en el estándar C o en el estándar C ++. Esto se considera una característica puramente específica del sistema operativo y se especifica en el estándar POSIX, por ejemplo.

    Thorsten79 ha dado una buena sugerencia, es la biblioteca Boost.Filesystem. Sin embargo, puede ser un inconveniente en caso de que no desee tener dependencias de tiempo de enlace en forma binaria para su progtwig.

    Una buena alternativa que recomendaría es la colección de librerías STLSoft C ++ con encabezados al 100% Matthew Wilson (autor de libros de lectura obligatoria sobre C ++). Hay una fachada portátil PlatformSTL da acceso a la API específica del sistema: WinSTL para Windows y UnixSTL en Unix, por lo que es una solución portátil. Todos los elementos específicos del sistema se especifican con el uso de rasgos y políticas, por lo que es un marco extensible. Hay una biblioteca de sistema de archivos proporcionada, por supuesto.

    Una solución de biblioteca (aunque sé que esto no se solicitó). Si usa Qt: QCoreApplication::applicationDirPath()