문제

C/C ++를 사용하여 프로그램이 실행되는 곳에서 디렉토리의 전체 경로를 얻는 플랫폼 공유 및 파일 시스템 공유 방법이 있습니까? 현재 작업 디렉토리와 혼동하지 마십시오. (도서관은 CLIB 또는 STL과 같은 표준의 도서관이 아닌 한 도서관을 제안하지 마십시오.)

(플랫폼/파일 시스템 공연 방법이없는 경우, 특정 파일 시스템에 대한 Windows 및 Linux에서 작동한다는 제안도 환영합니다.)

도움이 되었습니까?

해결책

실행 앱의 전체 경로를 얻는 코드는 다음과 같습니다.

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;

다른 팁

프로그램이 처음 시작될 때 현재 디렉토리를 가져 오면 프로그램이 시작된 디렉토리가 효과적으로 시작되었습니다. 변수에 값을 저장하고 프로그램의 뒷부분을 참조하십시오. 이것은 구별됩니다 현재 실행 가능한 프로그램 파일을 보유하는 디렉토리. 반드시 같은 디렉토리는 아닙니다. 누군가 명령 프롬프트에서 프로그램을 실행하면 프로그램이 로부터 달아 나다 프로그램 파일이 다른 곳에있는 경우에도 명령 프롬프트의 현재 작업 디렉토리.

GetCWD는 POSIX 기능이며 모든 POSIX 호환 플랫폼에서 상자 밖으로 지원됩니다. 당신은 특별한 일을 할 필요가 없습니다 (유닉스에서 올바른 헤더를 unix 및 direct.h를 기울이는 것 외에도 Windows에서는).

C 프로그램을 작성하므로 시스템의 모든 프로세스 (특별히 제작 된 예외를 피하기)에 의해 연결된 기본 C 실행 시간 라이브러리와 연결되며 기본적 으로이 기능을 포함합니다. CRT는 외부 라이브러리로 간주되지 않습니다. 기본 표준 호환 인터페이스를 OS에 제공하기 때문입니다.

Windows에서 GetCWD 기능은 _GetCWD에 찬성하여 더 이상 사용되지 않았습니다. 나는 당신이 이런 방식으로 그것을 사용할 수 있다고 생각합니다.

#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);

이것은에서 나온 것입니다 cplusplus 포럼

Windows :

#include <string>
#include <windows.h>

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

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 );
}

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 );
}

라이브러리가없는 표준 방식을 원한다면 : 아니요. 디렉토리의 전체 개념은 표준에 포함되지 않습니다.

근거리 지표 Lib에 대한 일부 (휴대용) 의존성에 동의하는 경우 : 부스트의 파일 시스템 라이브러리 그리고 initial_path ().

당신이 얻을 수있는만큼 가까운 IMHO, 좋은 카르마와 함께 (부스트는 잘 확립 된 고품질 라이브러리 세트입니다)

파일 시스템 ts 이제 표준입니다 (GCC 5.3+ 및 Clang 3.9+의 지원)이므로 사용할 수 있습니다. current_path() 그것으로부터 기능 :

GCC (5.3+)에서 파일 시스템을 포함하려면 사용해야합니다.

#include <experimental/filesystem>

코드를 연결하십시오 -lstdc++fs 깃발.

Microsoft Visual Studio와 함께 파일 시스템을 사용하려면 이것을 읽으십시오.

나는이 일에 답을 던지는 것이 매우 늦었다는 것을 알고 있지만 답은 내 자신의 해결책만큼 나에게 유용하지 않다는 것을 알았습니다. CWD에서 빈 폴더로 경로를 얻는 매우 간단한 방법은 다음과 같습니다.

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

이제 이것을 상대 경로의 기반으로 사용할 수 있습니다. 예를 들어이 디렉토리 구조가 있습니다.

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

소스 코드를 BIN에 컴파일하고 테스트로 로그를 작성하고 싶습니다.이 줄을 코드에 추가 할 수 있습니다.

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

전체 경로, 별칭 등을 사용하여 Linux 에서이 접근법을 시도했으며 잘 작동합니다.

노트:

Windows에있는 경우 ''를 '/'가 아닌 파일 분리기로 사용해야합니다. 예를 들어 다음과 같은 탈출해야합니다.

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

나는 이것이 효과가 있지만 테스트되지 않았다고 생각하므로, 그것이 작동하지 않으면 주석을 높이거나 고치하지 않으면 감사 할 것입니다.

아니요, 표준 방법이 없습니다. C/C ++ 표준은 디렉토리 (또는 다른 파일 시스템 조직)의 존재를 고려하지 않다고 생각합니다.

Windows에서 getModuleFilename () 현재 프로세스의 실행 파일로의 전체 경로를 반환합니다. hmodule 매개 변수가 설정됩니다 없는. 나는 리눅스를 도울 수 없다.

또한 현재 디렉토리 또는 프로그램 이미지/실행 파일이있는 디렉토리를 원하는지 여부를 명확히해야합니다. 당신의 질문은이 시점에서 약간 모호합니다.

아마도 현재 작업 디렉토리를 ArgV [0]와 연결시킬 수 있습니까? 그것이 Windows에서 작동하는지 확실하지 않지만 Linux에서 작동합니다.

예를 들어:

#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;
}

실행되면 출력 :

Jeremy@jeremy-desktop : ~/goodtop $ ./test
/home/jeremy/desktop/./test

해당 목적으로 ArgV [0]를 사용할 수 없습니다. 일반적으로 실행 파일에 대한 전체 경로가 포함되어 있지만 Nessesly가 아닌 프로세스는 현장에서 임의의 가치로 생성 될 수 있습니다.

또한 현재 디렉토리와 실행 파일이있는 디렉토리는 두 가지 다른 것이므로 GetCWD ()도 도움이되지 않습니다.

Windows에서 getModuleFilename (), Linux read/dev/proc/에서Procid/.. 파일.

창에서 가장 간단한 방법은 사용하는 것입니다 _get_pgmptr 기능 stdlib.h 실행 파일 이름을 포함하여 실행 파일의 절대 경로를 나타내는 문자열에 대한 포인터를 얻으려면.

char* path;
_get_pgmptr(&path);
printf(path); // Example output: C:/Projects/Hello/World.exe

Win32의 경우 GetCurrentDirectory 트릭을해야합니다.

여기에 뒤늦게 쌓이기 위해 ...

언어는 기본 파일 시스템의 비율이 없기 때문에 표준 솔루션이 없으므로 다른 사람들이 말했듯이 디렉토리 기반 파일 시스템의 개념은 C / C ++ 언어의 범위를 벗어납니다.

또한 현재 작업 디렉토리를 원하지 않지만 프로그램이 실행중인 디렉토리를 원합니다. 프로그램이 어떻게 어디에 있는지 고려해야합니다. 즉, 포크 등을 통해 새로운 프로세스로 스폰되었습니다. 솔루션에서 알 수 있듯이 프로그램이 진행되는 디렉토리를 얻으려면 해당 정보가 해당 정보를 얻어야합니다. 해당 정보는 해당 운영 체제의 프로세스 제어 구조 에서이 질문에 대한 유일한 권한입니다. 따라서 정의상 OS 특정 솔루션입니다.

콘솔의 Windows 시스템의 경우 시스템을 사용할 수 있습니다 (dir) 명령. 콘솔은 디렉토리 등에 대한 정보를 제공합니다. dir 명령 cmd. 그러나 유닉스와 같은 시스템의 경우,이 명령이 실행되면 Bash 명령을 읽으십시오. ls 디렉토리를 표시하지 않습니다 ...

예시:

int main()
{
    system("dir");
    system("pause"); //this wait for Enter-key-press;
    return 0;
}
#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);
}

The linux bash command which progname will report a path to program.

Even if one could issue the which command from within your program and direct the output to a tmp file and the program subsequently reads that tmp file, it will not tell you if that program is the one executing. It only tells you where a program having that name is located.

What is required is to obtain your process id number, and to parse out the path to the name

In my program I want to know if the program was executed from the user's bin directory or from another in the path or from /usr/bin. /usr/bin would contain the supported version. My feeling is that in Linux there is the one solution that is portable.

For relative paths, here's what I did. I am aware of the age of this question, I simply want to contribute a simpler answer that works in the majority of cases:

Say you have a path like this:

"path/to/file/folder"

For some reason, Linux-built executables made in eclipse work fine with this. However, windows gets very confused if given a path like this to work with!

As stated above there are several ways to get the current path to the executable, but the easiest way I find works a charm in the majority of cases is appending this to the FRONT of your path:

"./path/to/file/folder"

Just adding "./" should get you sorted! :) Then you can start loading from whatever directory you wish, so long as it is with the executable itself.

EDIT: This won't work if you try to launch the executable from code::blocks if that's the development environment being used, as for some reason, code::blocks doesn't load stuff right... :D

EDIT2: Some new things I have found is that if you specify a static path like this one in your code (Assuming Example.data is something you need to load):

"resources/Example.data"

If you then launch your app from the actual directory (or in Windows, you make a shortcut, and set the working dir to your app dir) then it will work like that. Keep this in mind when debugging issues related to missing resource/file paths. (Especially in IDEs that set the wrong working dir when launching a build exe from the IDE)

On POSIX platforms, you can use getcwd().

On Windows, you may use _getcwd(), as use of getcwd() has been deprecated.

For standard libraries, if Boost were standard enough for you, I would have suggested Boost::filesystem, but they seem to have removed path normalization from the proposal. You may have to wait until TR2 becomes readily available for a fully standard solution.

Boost Filesystem's initial_path() behaves like POSIX's getcwd(), and neither does what you want by itself, but appending argv[0] to either of them should do it.

You may note that the result is not always pretty--you may get things like /foo/bar/../../baz/a.out or /foo/bar//baz/a.out, but I believe that it always results in a valid path which names the executable (note that consecutive slashes in a path are collapsed to one).

I previously wrote a solution using envp (the third argument to main() which worked on Linux but didn't seem workable on Windows, so I'm essentially recommending the same solution as someone else did previously, but with the additional explanation of why it is actually correct even if the results are not pretty.

As Minok mentioned, there is no such functionality specified ini C standard or C++ standard. This is considered to be purely OS-specific feature and it is specified in POSIX standard, for example.

Thorsten79 has given good suggestion, it is Boost.Filesystem library. However, it may be inconvenient in case you don't want to have any link-time dependencies in binary form for your program.

A good alternative I would recommend is collection of 100% headers-only STLSoft C++ Libraries Matthew Wilson (author of must-read books about C++). There is portable facade PlatformSTL gives access to system-specific API: WinSTL for Windows and UnixSTL on Unix, so it is portable solution. All the system-specific elements are specified with use of traits and policies, so it is extensible framework. There is filesystem library provided, of course.

A library solution (although I know this was not asked for). If you happen to use Qt: QCoreApplication::applicationDirPath()

Use realpath() in stdlib.h like this:

char *working_dir_path = realpath(".", NULL);

Works with starting from C++11, using experimental filesystem, and C++14-C++17 as well using official filesystem.

application.h:

#pragma once

//
// https://en.cppreference.com/w/User:D41D8CD98F/feature_testing_macros
//
#ifdef __cpp_lib_filesystem
#include <filesystem>
#else
#include <experimental/filesystem>

namespace std {
    namespace filesystem = experimental::filesystem;
}
#endif

std::filesystem::path getexepath();

application.cpp:

#include "application.h"
#ifdef _WIN32
#include <windows.h>    //GetModuleFileNameW
#else
#include <limits.h>
#include <unistd.h>     //readlink
#endif

std::filesystem::path getexepath()
{
#ifdef _WIN32
    wchar_t path[MAX_PATH] = { 0 };
    GetModuleFileNameW(NULL, path, MAX_PATH);
    return path;
#else
    char result[PATH_MAX];
    ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
    return std::string(result, (count > 0) ? count : 0);
#endif
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top