Jak uzyskać katalog, z którego działa program?
Czy istnieje metoda platform-agnostic i filesystem-Agnostic, aby uzyskać pełną ścieżkę katalogu, z którego program jest uruchomiony przy użyciu C / C++? Nie mylić z bieżącym katalogiem roboczym. (Proszę nie sugerować bibliotek, chyba że są one standardowe, takie jak clib lub STL.)
(jeśli nie ma metody agnostycznej dla platformy/systemu plików, sugestie, które działają w Windows i Linux dla określonych systemów plików są również mile widziane.)
20 answers
Oto kod, aby uzyskać pełną ścieżkę do wykonywanej aplikacji:
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;
Jeśli pobierasz bieżący katalog przy pierwszym uruchomieniu programu, to faktycznie masz katalog, z którego program został uruchomiony. Przechowuj wartość w zmiennej i odwołaj się do niej później w programie. Różni się to od katalogu, w którym znajduje się bieżący plik wykonywalny programu . Niekoniecznie jest to ten sam katalog; jeśli ktoś uruchamia program z wiersza polecenia, to program jest uruchamiany z bieżącego katalogu roboczego wiersza polecenia nawet chociaż plik programu mieszka gdzie indziej.
Getcwd jest funkcją POSIX i jest obsługiwana po wyjęciu z pudełka przez wszystkie platformy zgodne z POSIX. Nie musiałbyś robić nic specjalnego (poza wstawianiem odpowiednich nagłówków unistd.h na Unix i direct.h na windows).
Ponieważ tworzysz program C, połączy się on z domyślną biblioteką czasu uruchamiania c, do której są powiązane wszystkie procesy w systemie (uniknięto specjalnie spreparowanych wyjątków) i domyślnie będzie zawierał tę funkcję. CRT nigdy nie jest uważana za bibliotekę zewnętrzną, ponieważ zapewnia podstawowy interfejs zgodny ze standardem dla systemu operacyjnego.
W systemie Windows Funkcja getcwd została wycofana na rzecz _getcwd. Myślę, że możesz go użyć w ten sposób.
#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);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:39
To jest z cplusplus forum
W systemie windows:
#include <string>
#include <windows.h>
std::string getexepath()
{
char result[ MAX_PATH ];
return std::string( result, GetModuleFileName( NULL, result, MAX_PATH ) );
}
Na Linuksie:
#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 );
}
Na 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 );
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-24 15:59:23
Jeśli chcesz standardową drogę bez bibliotek: Nie. Cała koncepcja katalogu nie jest zawarta w standardzie.
Jeśli zgadzasz się, że niektóre (przenośne) zależności od prawie standardowego lib jest w porządku: Użyj Boost ' S filesystem library i poproś o initial_path () .
IMHO jak najbliżej, z dobrą karmą (Boost to sprawdzony zestaw wysokiej jakości bibliotek)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-27 07:23:51
System plików TS jest teraz standardem (i obsługiwanym przez gcc 5.3+ i clang 3.9+), więc możesz użyć current_path()
Funkcja z niego:
std::string path = std::experimental::filesystem::current_path();
W gcc (5.3+) aby włączyć system plików musisz użyć:
#include <experimental/filesystem>
I połącz swój kod z -lstdc++fs
flagą.
Jeśli chcesz używać systemu plików z Microsoft Visual Studio, to przeczytaj to .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-11 11:38:29
Wiem, że jest bardzo późno, aby rzucić odpowiedź na ten jeden, ale okazało się, że żadna z odpowiedzi nie były tak przydatne dla mnie jak moje własne rozwiązanie. Bardzo prosty sposób na uzyskanie ścieżki z CWD do folderu bin jest następujący:
int main(int argc, char* argv[])
{
std::string argv_str(argv[0]);
std::string base = argv_str.substr(0, argv_str.find_last_of("/"));
}
Możesz teraz użyć tego jako podstawy dla swojej ścieżki względnej. Na przykład mam taką strukturę katalogów:
main
----> test
----> src
----> bin
I chcę skompilować mój kod źródłowy do bin i napisać log do testowania mogę po prostu dodać ten wiersz do mojego kod.
std::string pathToWrite = base + "/../test/test.log";
Próbowałem tego podejścia na Linuksie używając pełnej ścieżki, aliasu itp. i działa dobrze.
Uwaga:
Jeśli jesteś w systemie windows, powinieneś użyć ' \ 'jako separatora plików, a nie'/'. Będziesz musiał również uciec od tego na przykład:
std::string base = argv[0].substr(0, argv[0].find_last_of("\\"));
Myślę, że to powinno działać, ale nie testowałem, więc komentarz byłby mile widziany, jeśli to działa, lub poprawka, jeśli nie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-15 11:30:13
Nie, Nie ma standardowego sposobu. Uważam, że standardy C / C++ nie uwzględniają nawet istnienia katalogów (lub innych organizacji systemów plików).
W systemie Windows Funkcja GetModuleFileName () zwróci pełną ścieżkę do pliku wykonywalnego bieżącego procesu, gdy parametr hModule zostanie ustawiony na NULL. Nie mogę pomóc z Linuksem.
należy również wyjaśnić, czy chcesz bieżący katalog lub katalog, który program image / executable. W obecnej sytuacji Pańskie pytanie jest nieco niejednoznaczne w tej kwestii.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-27 07:35:51
Może połączyć bieżący katalog roboczy z argv [0]? Nie jestem pewien, czy to zadziała w Windows, ale działa w Linuksie.
Na przykład:
#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;
}
Po uruchomieniu wyświetla:
Jeremy @ jeremy-desktop:~ / Desktop$ ./ test
/ home / jeremy/pulpit / / test
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-27 07:39:11
Nie można używać argv[0] do tego celu, zazwyczaj zawiera on pełną ścieżkę do pliku wykonywalnego, ale nie jest to możliwe - proces może być utworzony z dowolną wartością w polu.
Pamiętaj również, że bieżący katalog i katalog z plikiem wykonywalnym to dwie różne rzeczy, więc getcwd() też Ci nie pomoże.
W systemie Windows użyj GetModuleFileName (), w Linuksie przeczytaj /dev/proc/procID/.. pliki.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-13 04:12:24
Dla Win32 GetCurrentDirectory powinno wystarczyć.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-27 07:21:01
Dla systemu Windows w konsoli można użyć polecenia system(dir
). A konsola daje informacje o katalogu itp. Przeczytaj o komendzie dir
w cmd
. Ale dla systemów uniksopodobnych, Nie wiem... Jeśli to polecenie jest uruchomione, przeczytaj polecenie bash. ls
nie wyświetla katalogu...
Przykład:
int main()
{
system("dir");
system("pause"); //this wait for Enter-key-press;
return 0;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-10 17:13:27
Tylko po to, by z opóźnieniem ułożyć tutaj,...
Nie ma standardowego rozwiązania, ponieważ języki te są niezależne od bazowych systemów plików, więc jak mówili inni, pojęcie systemu plików opartego na katalogach jest poza zakresem języków c / C++.
Poza tym, nie chcesz bieżącego katalogu roboczego, ale katalogu, w którym działa program, który musi wziąć pod uwagę, jak program dotarł do miejsca, w którym się znajduje - tj. czy powstał jako nowy proces przez fork, itp. Aby uzyskać katalog, w którym uruchomiony jest program, jak wykazały rozwiązania, należy uzyskać te informacje ze struktur sterowania procesami danego systemu operacyjnego, który jest jedynym organem w tej kwestii. Tak więc, z definicji, jest to rozwiązanie specyficzne dla systemu operacyjnego.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-27 23:50:14
W systemie Windows najprostszym sposobem jest użycie funkcji _get_pgmptr
w stdlib.h
, aby uzyskać wskaźnik do ciągu znaków, który reprezentuje absolutną ścieżkę do pliku wykonywalnego, w tym nazwę pliku wykonywalnego.
char* path;
_get_pgmptr(&path);
printf(path); // Example output: C:/Projects/Hello/World.exe
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-10 07:52:44
#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);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-19 17:20:58
Polecenie linux bash który progname zgłosi ścieżkę do programu.
Nawet jeśli można wydać polecenie which z programu i skierować wyjście do pliku tmp i programu następnie odczytuje ten plik tmp, nie powie Ci, czy ten program jest wykonywany. Informuje tylko, gdzie znajduje się program o tej nazwie.
Wymagane jest uzyskanie numeru identyfikacyjnego procesu i przetworzenie ścieżki do nazwy
In my program chcę wiedzieć czy program był wykonywane z katalogu bin użytkownika lub z innego w ścieżce lub z /usr / bin. /usr / bin będzie zawierał obsługiwaną wersję. Mam wrażenie, że w Linuksie jest jedyne rozwiązanie, które jest przenośne.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-22 15:46:54
Dla ścieżek względnych, oto co zrobiłem. Jestem świadomy wieku tego pytania, po prostu chcę wnieść prostszą odpowiedź, która działa w większości przypadków: {]}
Powiedz, że masz taką ścieżkę:
"path/to/file/folder"
Z jakiegoś powodu, pliki wykonywalne zbudowane na Linuksie wykonane w eclipse dobrze z tym współpracują. Jednak System windows jest bardzo zdezorientowany, jeśli podano taką ścieżkę do pracy!
Jak wspomniano powyżej istnieje kilka sposobów, aby uzyskać bieżącą ścieżkę do pliku wykonywalnego, ale najprostszym sposobem I find works urokiem w większości przypadków jest dołączenie tego do przodu swojej ścieżki:
"./path/to/file/folder"
Tylko dodaję "./ align = "left" / :) Wtedy możesz rozpocząć ładowanie z dowolnego katalogu, o ile jest to z samym programem wykonywalnym.
EDIT: to nie zadziała, jeśli spróbujesz uruchomić plik wykonywalny z code:: blocks, jeśli jest to używane środowisko programistyczne, ponieważ z jakiegoś powodu, code::blocks nie ładuje się poprawnie... : D
EDIT2: kilka nowych rzeczy, które mam okazało się, że jeśli podasz statyczną ścieżkę, taką jak ta w kodzie (zakładając przykład.dane trzeba załadować):"resources/Example.data"
Jeśli następnie uruchomić aplikację z rzeczywistego katalogu (lub w systemie Windows, można utworzyć skrót, i ustawić katalog roboczy do katalogu aplikacji) to będzie działać w ten sposób. Należy o tym pamiętać podczas debugowania problemów związanych z brakującymi ścieżkami zasobów/plików. (Szczególnie w Idach, które ustawiają źle działający katalog podczas uruchamiania build exe z IDE)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-02 01:34:04
Na platformach POSIX można użyć getcwd().
W systemie Windows możesz użyć _getcwd(), ponieważ użycie getcwd() zostało przestarzałe.
W przypadku bibliotek standardowych, gdyby Boost był wystarczająco standardowy dla Ciebie, zasugerowałbym Boost::filesystem, ale wydaje się, że usunęły normalizację ścieżek z propozycji. Być może będziesz musiał poczekać, aż TR2 stanie się łatwo dostępne na w pełni standardowe rozwiązanie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-27 07:31:38
Boost Filesystem initial_path()
zachowuje się jak POSIX getcwd()
i nie robi tego, co chcesz, ale dołączenie argv[0]
do jednego z nich powinno to zrobić.
Możesz zauważyć, że wynik nie zawsze jest ładny-możesz uzyskać rzeczy takie jak /foo/bar/../../baz/a.out
lub /foo/bar//baz/a.out
, ale wierzę, że zawsze powoduje to poprawną ścieżkę, która nazywa program wykonywalny(zauważ, że kolejne ukośniki w ścieżce są zwinięte do jednego).
Napisałem wcześniej rozwiązanie używając envp
(trzeciego argumentu do main()
, które działało na Linux, ale nie wydaje się działać na Windows, więc w zasadzie polecam to samo rozwiązanie, co ktoś inny zrobił wcześniej, ale z dodatkowym wyjaśnieniem, dlaczego jest to rzeczywiście poprawne, nawet jeśli wyniki nie są ładne.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-24 01:24:59
Jak wspomniano Minok, nie ma takiej funkcjonalności określonej w standardzie ini C lub C++. Jest to uważane za cechę czysto specyficzną dla systemu operacyjnego i jest określone na przykład w standardzie POSIX.
Thorsten79 napisał (a):Biblioteka systemu plików. Jednakże, może to być niewygodne w przypadku, gdy nie chcesz mieć żadnych zależności od czasu łącza w postaci binarnej dla Twojego programu.
Dobrą alternatywą polecam jest zbiór 100% tylko nagłówki Biblioteki STLSoft C++ Matthew Wilson (autor obowiązkowych książek o C++). Jest przenośne platformstl daje dostęp do specyficznego dla systemu API: WinSTL Dla Windows i UnixSTL na Unix, więc jest to rozwiązanie przenośne. Wszystkie elementy specyficzne dla systemu są określone za pomocą cech i zasad, więc jest to rozszerzalny framework. Oczywiście dostępna jest biblioteka systemu plików.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-28 00:26:18
Rozwiązanie biblioteczne (choć wiem, że o to nie proszono).
W przypadku stosowania Qt:
QCoreApplication::applicationDirPath()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-04 09:38:03