프로그램이 실행되는 디렉토리는 어떻게 얻습니까?
C / C ++를 사용하여 프로그램이 실행되고있는 디렉토리의 전체 경로를 가져 오는 플랫폼에 구애받지 않고 파일 시스템에 구애받지 않는 방법이 있습니까? 현재 작업 디렉토리와 혼동하지 마십시오. (clib 또는 STL과 같은 표준 라이브러리가 아닌 경우 라이브러리를 제안하지 마십시오.)
(플랫폼 / 파일 시스템과 무관 한 방법이 없다면, 특정 파일 시스템에 대해 Windows 및 Linux에서 작동하는 제안도 환영합니다.)
실행중인 앱의 전체 경로를 얻는 코드는 다음과 같습니다.
윈도우 :
int bytes = GetModuleFileName(NULL, pBuf, len);
if(bytes == 0)
return -1;
else
return bytes;
리눅스 :
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 호환 플랫폼에서 기본적으로 지원됩니다. 특별한 일을 할 필요는 없습니다 (Unixd.h에 올바른 헤더를 포함하고 Windows에 direct.h를 포함시키는 것 제외).
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);
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 );
}
라이브러리가없는 표준 방법을 원할 경우 : 아니오. 디렉토리의 전체 개념이 표준에 포함되지 않습니다.
근사 표준 라이브러리에 대한 (이동식) 의존성이 괜찮다면, Boost의 파일 시스템 라이브러리 를 사용하고 initial_path ()를 요청하십시오 .
좋은 업보로 얻을 수있는 가장 가까운 IMHO (부스트는 잘 확립 된 고품질 라이브러리 세트)
파일 시스템 TS 는 이제 표준 이며 gcc 5.3+ 및 clang 3.9+에서 지원되므로 다음과 같은 current_path()
기능을 사용할 수 있습니다 .
std::string path = std::experimental::filesystem::current_path();
gcc (5.3+)에서 파일 시스템을 포함하려면 다음을 사용해야합니다.
#include <experimental/filesystem>
코드와 -lstdc++fs
플래그를 연결하십시오 .
Microsoft Visual Studio에서 파일 시스템을 사용하려면 이 내용 을 읽으십시오 .
나는 이것에 대한 답변을 던지는 것이 매우 늦다는 것을 알고 있지만, 내 대답만큼 유용한 답변이 없다는 것을 알았습니다. CWD에서 bin 폴더로의 경로를 얻는 매우 간단한 방법은 다음과 같습니다.
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 에서이 접근법을 시도했지만 제대로 작동합니다.
노트:
창에있는 경우 '/'가 아닌 파일 구분 기호로 '\'를 사용해야합니다. 예를 들어 이것을 피해야합니다.
std::string base = argv[0].substr(0, argv[0].find_last_of("\\"));
나는 이것이 작동해야하지만 테스트되지는 않았다고 생각하므로 그것이 작동하면 의견을 주시면 안됩니다.
아니요, 표준적인 방법은 없습니다. C / C ++ 표준은 디렉토리 (또는 다른 파일 시스템 조직)의 존재조차 고려하지 않는다고 생각합니다.
Windows에서 hModule 매개 변수가 NULL 로 설정 되면 GetModuleFileName () 은 현재 프로세스의 실행 파일에 대한 전체 경로를 리턴합니다 . 나는 리눅스를 도울 수 없다.
또한 현재 디렉토리 또는 프로그램 이미지 / 실행 파일이있는 디렉토리를 원하는지 확인해야합니다. 그것은 당신의 질문이 약간 모호합니다.
현재 작업 디렉토리를 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 : ~ / Desktop $ ./test
/home/jeremy/Desktop/./test
Win32의 경우 GetCurrentDirectory 가 트릭을 수행해야합니다.
그 목적으로 argv [0]을 사용할 수 없습니다. 일반적으로 실행 파일에 대한 전체 경로를 포함하지만 반드시 그렇지는 않습니다. 프로세스는 필드에 임의의 값으로 생성 될 수 있습니다.
또한 현재 디렉토리와 실행 파일이있는 디렉토리는 서로 다른 두 가지이므로 getcwd ()는 도움이되지 않습니다.
Windows에서는 GetModuleFileName ()을 사용하고 Linux에서는 / dev / proc / procID / .. 파일을 읽으십시오 .
Windows에서 가장 간단한 방법은 _get_pgmptr
함수 를 사용 stdlib.h
하여 실행 파일 이름을 포함하여 실행 파일의 절대 경로를 나타내는 문자열에 대한 포인터를 얻는 것입니다.
char* path;
_get_pgmptr(&path);
printf(path); // Example output: C:/Projects/Hello/World.exe
늦게 여기에 쌓여서 ...
언어는 기본 파일 시스템과 무관하므로 표준 솔루션이 없으므로 디렉토리 기반 파일 시스템의 개념은 c / c ++ 언어의 범위를 벗어납니다.
또한 현재 작업 디렉토리가 아니라 프로그램이 실행중인 디렉토리를 원합니다.이 디렉토리는 프로그램이 현재 위치에 어떻게 도달했는지를 고려해야합니다. 즉 포크를 통해 새로운 프로세스로 생성되었습니다. 솔루션이 시연 한 것처럼 프로그램이 실행중인 디렉토리를 가져 오려면 해당 운영 체제의 프로세스 제어 구조에서 해당 정보를 가져와야합니다.이 정보는이 질문에 대한 유일한 권한입니다. 따라서 정의에 따라 OS 특정 솔루션입니다.
콘솔의 Windows 시스템의 경우 system ( 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);
}
progname 이 linux bash 명령 으로 프로그램 경로를보고합니다.
프로그램 내에서 which 명령을 실행하여 출력을 tmp 파일로 보내고 프로그램이 해당 tmp 파일을 읽더라도 해당 프로그램이 실행 중인지 여부는 알려주지 않습니다. 해당 이름의 프로그램이있는 위치 만 알려줍니다.
필요한 것은 프로세스 ID 번호를 얻고 이름의 경로를 파싱하는 것입니다.
내 프로그램에서 프로그램이 사용자의 bin 디렉토리 또는 경로의 다른 디렉토리 또는 / usr / bin에서 실행되었는지 알고 싶습니다. / usr / bin은 지원되는 버전을 포함합니다. 제 생각에는 리눅스에는 휴대용 솔루션이 있습니다.
상대 경로의 경우 여기에 내가 한 일이 있습니다. 나는이 질문의 나이를 알고 있으며, 대부분의 경우에 작동하는 더 간단한 답변을 제공하고 싶습니다.
다음과 같은 경로가 있다고 가정하십시오.
"path/to/file/folder"
어떤 이유로, 이클립스로 만든 리눅스 빌드 실행 파일은 이것과 잘 작동합니다. 그러나 이와 같은 경로를 사용하면 Windows가 매우 혼란 스럽습니다!
위에서 언급했듯이 실행 파일의 현재 경로를 얻는 방법은 여러 가지가 있지만 대부분의 경우 가장 쉬운 방법은 경로의 FRONT에 추가하는 것입니다.
"./path/to/file/folder"
"./"를 추가하면 정렬됩니다! :) 그런 다음 실행 파일 자체가있는 한 원하는 디렉토리에서로드를 시작할 수 있습니다.
편집 : 어떤 이유로 사용중인 개발 환경 인 경우 code :: blocks에서 실행 파일을 시작하려고하면 작동하지 않습니다.
EDIT2 : 내가 찾은 몇 가지 새로운 점은 코드에서 이와 같은 정적 경로를 지정하면 (Example.data 가로 드 해야하는 것으로 가정 함)입니다.
"resources/Example.data"
그런 다음 실제 디렉토리에서 앱을 시작하거나 Windows에서 바로 가기를 만들고 작업 디렉토리를 앱 디렉토리로 설정하면 그렇게 작동합니다. 누락 된 리소스 / 파일 경로와 관련된 문제를 디버깅 할 때이 점을 명심하십시오. (특히 IDE에서 빌드 exe를 시작할 때 잘못된 작동 디렉토리를 설정 한 IDE에서)
라이브러리 솔루션 (요청하지는 않았지만). Qt를 사용하는 경우 :QCoreApplication::applicationDirPath()
POSIX 플랫폼에서는 getcwd ()를 사용할 수 있습니다 .
Windows에서는 사용할 수 있습니다 ) (_getcwd 의 사용으로, ()에 getcwd 사용되지 않습니다.
표준 라이브러리의 경우 Boost가 충분히 표준이라면 Boost :: filesystem을 제안했지만 제안에서 경로 정규화를 제거 한 것 같습니다. 완전한 표준 솔루션을 위해 TR2를 즉시 사용할 수있을 때까지 기다려야 할 수도 있습니다 .
Boost Filesystem initial_path()
은 POSIX처럼 작동하며 getcwd()
원하는 것을 스스로 수행하지는 않지만 argv[0]
그중 하나에 추가 하면됩니다.
당신은 결과는 항상 꽤되지 않습니다 점에 유의 할 수 있습니다 - 당신은 같은 것을 얻을 수 /foo/bar/../../baz/a.out
하거나 /foo/bar//baz/a.out
,하지만 난 항상 어떤 이름이 실행 파일 (경로의 연속 슬래시 하나에 붕괴되는 것을 참고) 유효한 경로 결과 믿습니다.
이전 에 (Linux에서는 효과가 있었지만 Windows에서는 작동하지 않는 envp
세 번째 주장을 사용하여 솔루션을 작성 main()
했으므로 다른 사람과 이전과 동일한 솔루션을 권장하지만 실제로는 왜 정확한지에 대한 추가 설명과 함께 결과가 예쁘지 않더라도.
으로 Minok가 언급 한, 그런 기능은 INI C의 표준 또는 C ++ 표준을 지정하지 있습니다. 이것은 OS 고유의 기능으로 간주되며 POSIX 표준에 지정되어 있습니다.
Thorsten79 는 Boost.Filesystem 라이브러리라는 좋은 제안을했습니다. 그러나 링크 시간 종속성을 프로그램의 이진 형식으로 사용하지 않으려는 경우 불편할 수 있습니다.
내가 추천하는 좋은 대안은 100 % 헤더 전용 STLSoft C ++ 라이브러리의 수집입니다. Matthew Wilson (C ++에 대한 필독 서적 저자). 이식 가능한 외관 PlatformSTL은 시스템 별 API (Windows 용 WinSTL 및 Unix의 UnixSTL)에 대한 액세스를 제공하므로 휴대용 솔루션입니다. 모든 시스템 별 요소는 특성과 정책을 사용하여 지정되므로 확장 가능한 프레임 워크입니다. 물론 파일 시스템 라이브러리가 제공됩니다.
다음 realpath()
과 stdlib.h
같이 사용하십시오 .
char *working_dir_path = realpath(".", NULL);
실험 파일 시스템을 사용하는 C ++ 11부터, 공식 파일 시스템을 사용하는 C ++ 14-C ++ 17에서 작동합니다.
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
}
참고 URL : https://stackoverflow.com/questions/143174/how-do-i-get-the-directory-that-a-program-is-running-from
'IT' 카테고리의 다른 글
Jest를 사용하여 단일 테스트를 어떻게 실행합니까? (0) | 2020.04.01 |
---|---|
파이썬에서 큰 파일을 읽는 게으른 방법? (0) | 2020.04.01 |
CSS3 애니메이션 종료시 최종 상태 유지 (0) | 2020.04.01 |
커서 위치에서 시작하여 VIM에서 줄을 빠르게 삭제하려면 어떻게해야합니까? (0) | 2020.04.01 |
Python 2.7에서 하위 프로세스의 출력을 숨기는 방법 (0) | 2020.04.01 |