¿Existe un método independiente de la plataforma y del sistema de archivos para obtener la ruta completa del directorio desde donde se ejecuta un programa usando C / C ++? No debe confundirse con el directorio de trabajo actual. (No sugiera bibliotecas a menos que sean estándar como clib o STL).
(Si no hay un método independiente de plataforma / sistema de archivos, las sugerencias que funcionan en Windows y Linux para sistemas de archivos específicos también son bienvenidas).
c++
c
working-directory
Ashwin Nanjappa
fuente
fuente
argv[0]
, la técnica dependerá mucho del sistema operativo.#include <windows.h>
, Windows coloca automáticamente unachar*
ruta ejecutable_pgmptr
. No necesita llamar a funciones adicionales o asumir basura si solo está trabajando en Windows._pgmptr
. La documentación de MSDN indica que las variables_pgmptr
y_wpgmptr
están en desuso, y debe usar la función_get_pgmptr(char**)
o en su_get_wpgmptr(wchar_t**)
lugar. MSDNRespuestas:
Aquí hay un código para obtener la ruta completa a la aplicación en ejecución:
Ventanas:
Linux:
fuente
/proc
parte de mí, muere un poco. Todo el mundo no es Linux, e incluso en una plataforma que/proc
se debe considerar sujetos al cambio de versión en versión, arco a arco, etcchar pBuf[256]; size_t len = sizeof(pBuf);
para dejar la solución más clara.Si obtiene el directorio actual cuando se inicia su programa, entonces efectivamente tiene el directorio desde el que se inició su programa. Almacene el valor en una variable y consúltelo más adelante en su programa. Esto es distinto del directorio que contiene el archivo de programa ejecutable actual . No es necesariamente el mismo directorio; si alguien ejecuta el programa desde un símbolo del sistema, el programa se ejecuta desde el directorio de trabajo actual del símbolo del sistema aunque el archivo del programa 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 correctos unistd.h en Unix y direct.h en windows).
Como está creando un programa en C, se vinculará con la biblioteca de tiempo de ejecución de c predeterminada a la que están vinculados TODOS los procesos en el sistema (se evitan las excepciones especialmente diseñadas) e incluirá esta función de manera predeterminada. El CRT nunca se considera una biblioteca externa porque proporciona la interfaz básica compatible con el sistema operativo.
En Windows, la función getcwd ha quedado en desuso a favor de _getcwd. Creo que podrías usarlo de esta manera.
fuente
Esto es del foro cplusplus
En windows:
En Linux:
En HP-UX:
fuente
error: cannot convert 'char*' to 'LPWCH {aka wchar_t*}' for argument '2' to 'DWORD GetModuleFileNameW(HMODULE, LPWCH, DWORD)'
al compilar con MinGW.Si desea una forma estándar sin bibliotecas: No. El concepto completo de un directorio no está incluido en el estándar.
Si está de acuerdo en que una dependencia (portátil) de una lib casi estándar está bien: use la biblioteca del sistema de archivos de Boost y solicite initial_path () .
En mi humilde opinión eso es lo más cerca que puede llegar, con buen karma (Boost es un conjunto de bibliotecas de alta calidad bien establecido)
fuente
El sistema de archivos TS ahora es un estándar (y es compatible con gcc 5.3+ y clang 3.9+), por lo que puede usar la
current_path()
función de él:En gcc (5.3+) para incluir el sistema de archivos que necesita usar:
y vincule su código con la
-lstdc++fs
bandera.Si desea utilizar el Sistema de archivos con Microsoft Visual Studio, lea esto .
fuente
1-2) Returns the absolute path of the current working directory, obtained as if by POSIX getcwd. (2) returns path() if error occurs.
referenciado , Downvoted, ya que el OP pregunta específicamente sobre la ruta actual del ejecutable en lugar del directorio de trabajo actual.Sé que es muy tarde en el día para dar una respuesta a esta, 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 de su CWD a su carpeta bin es la siguiente:
Ahora puede usar esto como base para su ruta relativa. Entonces, por ejemplo, tengo esta estructura de directorio:
y quiero compilar mi código fuente en bin y escribir un registro para probar, solo puedo agregar esta línea a mi código.
He intentado este enfoque en Linux usando la ruta completa, alias, etc. y funciona bien.
NOTA:
Si está en Windows, debe usar un '\' como separador de archivos, no '/'. Tendrás que escapar de esto también, por ejemplo:
Creo que esto debería funcionar, pero no lo he probado, por lo que se agradecería comentar si funciona o una solución si no.
fuente
argv[0]
es una muy buena idea, pero desafortunadamente lo que obtengo en Linux es "./my_executable_name" o "./make/my_executable_name". Básicamente, lo que obtengo depende completamente de cómo loNo, no hay una forma estándar. Creo que los estándares C / C ++ ni siquiera consideran la existencia de directorios (u otras organizaciones de sistemas de archivos).
En Windows, GetModuleFileName () devolverá la ruta completa al archivo ejecutable del proceso actual cuando el parámetro hModule se establece en NULL . No puedo ayudar con Linux.
También debe aclarar si desea el directorio actual o el directorio donde reside la imagen / ejecutable del programa. Tal como está, su pregunta es un poco ambigua en este punto.fuente
En Windows, la forma más sencilla es utilizar la
_get_pgmptr
funciónstdlib.h
para obtener un puntero a una cadena que represente la ruta absoluta al ejecutable, incluido el nombre del ejecutable.fuente
¿Quizás 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:
Cuando se ejecuta, genera:
fuente
Para Win32 GetCurrentDirectory debería hacer el truco.
fuente
No puede usar argv [0] para ese propósito, generalmente contiene la ruta completa al ejecutable, pero no necesariamente; el proceso podría crearse con un valor arbitrario en el campo.
También tenga en cuenta que el directorio actual y el directorio con el ejecutable son dos cosas diferentes, por lo que getcwd () tampoco lo ayudará.
En Windows, use GetModuleFileName (), en los archivos read / dev / proc / procID / .. de Linux .
fuente
Solo para atrasarme aquí, ...
no existe una solución estándar, porque los lenguajes 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 alcance de los lenguajes c / c ++.
Además de eso, no desea el directorio de trabajo actual, sino el directorio en el que se ejecuta el programa, que debe tener en cuenta cómo llegó el programa a donde está, es decir, se generó como un nuevo proceso a través de un tenedor, etc. Para obtener el directorio en el que se ejecuta un programa, como lo han demostrado las soluciones, es necesario que obtenga esa información de las estructuras de control de procesos 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.
fuente
Para el sistema Windows en la consola, puede usar el
dir
comando system ( ). Y la consola le brinda información sobre el directorio, etc. Lea sobre eldir
comando encmd
. Pero para sistemas tipo Unix, no sé ... Si se ejecuta este comando, lea el comando bash.ls
no muestra el directorio ...Ejemplo:
fuente
fuente
En las 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, le habría sugerido el sistema de archivos Boost ::, pero parecen haber 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.
fuente
Para caminos relativos, esto es lo que hice. Soy consciente de la antigüedad de esta pregunta, simplemente quiero aportar una respuesta más simple que funcione en la mayoría de los casos:
Digamos que tienes un camino como este:
Por alguna razón, los ejecutables creados con Linux hechos en eclipse funcionan bien con esto. Sin embargo, Windows se confunde mucho si se le da una ruta como esta para trabajar.
Como se indicó anteriormente, hay varias formas 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:
¡Solo agregar "./" debería ordenarlo! :) Entonces puede comenzar a cargar desde el directorio que desee, siempre que sea con el ejecutable mismo.
EDITAR: Esto no funcionará si intenta iniciar el ejecutable desde code :: blocks si ese es el entorno de desarrollo que se está utilizando, ya que por alguna razón, code :: blocks no carga las cosas correctamente ...: D
EDIT2: Algunas cosas nuevas que he encontrado es que si especifica una ruta estática como esta en su código (Suponiendo que Example.data es algo que necesita cargar):
Si luego inicia su aplicación desde el directorio real (o en Windows, crea un acceso directo y establece el directorio de trabajo en el directorio de la aplicación), funcionará así. Tenga esto en cuenta al depurar problemas relacionados con la falta de rutas de recursos / archivos. (Especialmente en IDE que establecen el directorio de trabajo incorrecto al iniciar un exe de compilación desde el IDE)
fuente
Una solución de biblioteca (aunque sé que esto no fue solicitado). Si usa Qt:
QCoreApplication::applicationDirPath()
fuente
Solo mis dos centavos, pero ¿el siguiente código no funciona de manera portátil en C ++ 17?
Parece que funciona para mí en Linux al menos.
Basado en la idea anterior, ahora tengo:
Con implementación:
Y truco de inicialización en
main()
:Gracias @Sam Redway por la idea argv [0]. Y, por supuesto, entiendo que C ++ 17 no existió durante muchos años cuando el OP hizo la pregunta.
fuente
Boost Filesystem se
initial_path()
comporta como POSIXgetcwd()
, y tampoco hace lo que quiere por sí mismo, pero agregarloargv[0]
a cualquiera de ellos debería hacerlo.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 diagonales consecutivas en una ruta se colapsan en una).Anteriormente escribí una solución usando
envp
(el tercer argumento en elmain()
que funcionó en Linux pero no parecía viable en Windows, por lo que esencialmente estoy recomendando la misma solución que otra persona lo hizo anteriormente, pero con la explicación adicional de por qué es realmente correcto incluso si los resultados no son bonitos.fuente
Como mencionó Minok , no hay tal funcionalidad especificada en el estándar C ni 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 inconveniente en caso de que no desee tener dependencias de tiempo de enlace en forma binaria para su programa.
Una buena alternativa que recomendaría es la colección de bibliotecas STLSoft C ++ 100% solo con encabezados Matthew Wilson (autor de libros de lectura obligada 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.
fuente
El comando linux bash cuyo nombre de programa informará una ruta al programa.
Incluso si uno pudiera emitir el comando qué desde su programa y dirigir la salida a un archivo tmp y el programa posteriormente lee ese archivo tmp, no le dirá si ese programa es el que se está ejecutando. Solo le dice dónde se encuentra un programa con ese nombre.
Lo que se requiere es obtener su número de identificación de proceso y analizar la ruta al nombre
En mi programa, quiero saber si el programa 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 una solución que es portátil.
fuente
Utilizar
realpath()
enstdlib.h
este aspecto:fuente
Funciona comenzando desde C ++ 11, usando un sistema de archivos experimental, y C ++ 14-C ++ 17 también usando un sistema de archivos oficial.
aplicación.h:
application.cpp:
fuente
std
. Para evitar esto, puede agregar los espacios de nombresstd::filesystem
ystd::experimental::filesystem
un tercer espacio de nombres de su elección, o simplemente usarusing std::filesystem::path
, si no le importa agregar la declaraciónpath
al espacio de nombres global.