c++ - getcurrentdirectory c#
¿Cómo obtengo el directorio desde el que se ejecuta un programa? (20)
¿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 <stdio.h>
#include <unistd.h>
#include <string.h>
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
¿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 utilizando C / C ++? No debe confundirse con el directorio de trabajo actual. (Por favor, no sugiera bibliotecas a menos que sean las estándar como clib o STL).
(Si no existe un método independiente de la plataforma / sistema de archivos, las sugerencias que funcionan en Windows y Linux para sistemas de archivos específicos también son bienvenidas).
Aquí está el código para obtener la ruta completa a la aplicación en 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;
Como mencionó Minok , no existe ninguna funcionalidad especificada en el estándar C o en el estándar C ++. Se considera que es una función 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 quiera tener dependencias de tiempo de enlace en forma binaria para su programa.
Una buena alternativa que recomendaría es la recopilación de bibliotecas STLSoft C ++ 100% solo para encabezados, 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 características y políticas, por lo que es un marco extensible. Hay una biblioteca de sistema de archivos, por supuesto.
El comando linux bash cuyo nombre de programa informará una ruta al programa.
Incluso si uno pudiera emitir el comando dentro de su programa y dirigir la salida a un archivo tmp y el programa posteriormente lea ese archivo tmp, no le dirá si ese programa es el que se está ejecutando. Solo le indica dónde se encuentra un programa que tiene 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 soportada. Mi sensación es que en Linux hay una solución que es portátil.
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 función current_path()
desde allí:
std::string path = std::experimental::filesystem::current_path();
En gcc (5.3+) para incluir el sistema de archivos necesitas usar:
#include <experimental/filesystem>
y vincule su código con la -lstdc++fs
.
Si desea utilizar el sistema de archivos con Microsoft Visual Studio, lea esto .
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 del ejecutable.
char* path;
_get_pgmptr(&path);
printf(path); // Example output: C:/Projects/Hello/World.exe
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, hubiera sugerido Boost :: filesystem, pero parece que han eliminado la normalización de ruta de la propuesta. Es posible que deba esperar hasta que TR2 esté disponible para una solución completamente estándar.
Esto es del foro cplusplus.
En las ventanas:
#include <string>
#include <windows.h>
std::string getexepath()
{
char result[ MAX_PATH ];
return std::string( result, GetModuleFileName( NULL, result, MAX_PATH ) );
}
En Linux:
#include <string>
#include <limits.h>
#include <unistd.h>
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 <string>
#include <limits.h>
#define _PSTAT64
#include <sys/pstat.h>
#include <sys/types.h>
#include <unistd.h>
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 );
}
No puede usar argv [0] para ese propósito, por lo general contiene una ruta completa al ejecutable, pero no necesariamente, el proceso podría crearse con un valor arbitrario en el campo.
Además, 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 Linux lea / dev / proc / procID / .. archivos.
No, no hay una manera 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 esté establecido en NULL . No puedo ayudar con Linux.
También debe aclarar si desea el directorio actual o el directorio en el que reside la imagen / ejecutable del programa. En su forma actual su pregunta es un poco ambigua en este punto.
Para Win32 msdn.microsoft.com/en-us/library/aa364934(VS.85).aspx debe hacer el truco.
Para el sistema de 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 sistemas similares a Unix, no sé ... Si este comando se ejecuta, lea el comando bash. ls
no muestra el directorio ...
Ejemplo:
int main()
{
system("dir");
system("pause"); //this wait for Enter-key-press;
return 0;
}
Por caminos relativos, esto es lo que hice. Soy consciente de la edad de esta pregunta, simplemente quiero contribuir con una respuesta más simple que funcione 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 por Linux hechos en eclipse funcionan bien con esto. Sin embargo, Windows se confunde mucho si se le da un camino como este para trabajar.
Como se indicó anteriormente, hay varias maneras de obtener la ruta actual al ejecutable, pero la forma más sencilla que encuentro funciona de forma encantadora en la mayoría de los casos es agregar esto al FRENTE de su ruta:
"./path/to/file/folder"
¡Simplemente agregando "./" debería arreglarte! :) Luego puedes comenzar a cargar desde cualquier directorio que desees, siempre que sea con el ejecutable en sí.
EDITAR: Esto no funcionará si intenta ejecutar el ejecutable desde código :: bloques si ese es el entorno de desarrollo que se está utilizando, por alguna razón, el código :: bloques no carga correctamente ...
EDIT2: Algunas cosas nuevas que he encontrado es que si especifica una ruta estática como esta en su código (Asumir 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 configura el directorio de trabajo a su directorio de aplicación), entonces funcionará así. Tenga esto en cuenta al depurar los problemas relacionados con las rutas de archivos / recursos faltantes. (Especialmente en los IDE que establecen el directorio de trabajo incorrecto al iniciar un exe de compilación desde el IDE)
Sé que es muy tarde en el día para lanzar una respuesta a esta pregunta, pero encontré que ninguna de las respuestas me fue tan útil como mi propia solución. Una forma muy sencilla de obtener la ruta de acceso de su CWD a su carpeta bin es la siguiente:
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 puedes usar esto como base para tu ruta relativa. Así por ejemplo tengo esta estructura de directorio:
main
----> test
----> src
----> bin
y quiero compilar mi código fuente en un contenedor y escribir un registro para probar. Simplemente 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 bien.
NOTA:
Si está en Windows, debe usar un ''/' como separador de archivos, no ''/''. Tendrás que 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 se ha probado, por lo que se agradecería un comentario si funciona o una corrección si no lo fuera.
Sólo para acumular 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 alcance de los lenguajes c / c ++.
Además de eso, no desea el directorio de trabajo actual, sino el directorio en el que se está ejecutando 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 fork, etc. Para obtener el directorio en el que se está ejecutando un programa, como han demostrado las soluciones, se requiere 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 pregunta. Por lo tanto, por definición, es una solución específica del sistema operativo.
Si desea una forma estándar sin bibliotecas: No. El concepto completo de un directorio no está incluido en la norma.
Si está de acuerdo en que alguna dependencia (portátil) de una biblioteca casi estándar está bien: use la biblioteca del sistema de archivos de Boost y solicite la initial_path() .
En mi humilde opinión es lo más cercano que puede obtener, con buen karma (Boost es un conjunto de bibliotecas de alta calidad bien establecido)
Si recupera el directorio actual cuando se inicia el programa por primera vez, entonces efectivamente tiene el directorio desde el que se inició el 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, entonces 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).
Ya que está creando un programa en C, se vinculará con la biblioteca de tiempo de ejecución de c predeterminada, que está vinculada a TODOS los procesos del 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 compatible con el estándar básico para 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 <stdio.h> /* defines FILENAME_MAX */
#ifdef WINDOWS
#include <direct.h>
#define GetCurrentDir _getcwd
#else
#include <unistd.h>
#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);
Una solución de biblioteca (aunque sé que esto no fue solicitado). Si por casualidad usa Qt: QCoreApplication::applicationDirPath()
initial_path()
comporta como initial_path()
POSIX, y ninguno de los dos lo hace por sí solo, pero al añadir argv[0]
a cualquiera de ellos debería hacerlo.
Puede observar 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 al ejecutable (tenga en cuenta que las barras diagonales consecutivas en una ruta están contraídas en una).
Anteriormente escribí una solución usando envp
(el tercer argumento de main()
que funcionaba en Linux pero no parecía viable en Windows, por lo que básicamente recomiendo la misma solución que alguien más lo hizo anteriormente, pero con la explicación adicional de por qué En realidad es correcto incluso si los resultados no son bonitos.
#include <windows.h>
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);
}