Làm thế nào để tôi có được thư mục mà một chương trình đang chạy?


269

Có một phương pháp bất khả tri nền tảng và hệ thống tập tin để có được đường dẫn đầy đủ của thư mục từ nơi một chương trình đang chạy bằng C / C ++ không? Không được nhầm lẫn với thư mục làm việc hiện tại. (Vui lòng không đề xuất các thư viện trừ khi chúng là các thư viện tiêu chuẩn như clib hoặc STL.)

(Nếu không có phương pháp bất khả tri về nền tảng / hệ thống tập tin, các đề xuất hoạt động trong Windows và Linux cho các hệ thống tệp cụ thể cũng được hoan nghênh.)


@chakrit: Điều đó sẽ rất tuyệt. (Mặc dù vấn đề đó thường không xuất hiện trong Windows.)
Ashwin Nanjappa

2
Trừ khi bạn có thể trích xuất đường dẫn một cách đáng tin cậy argv[0], kỹ thuật sẽ phụ thuộc rất nhiều vào hệ điều hành.
David R Tribble

1
Chỉ cần làm rõ: 'thư mục hiện tại', hoặc 'thư mục mà chương trình đang chạy từ' (theo thuật ngữ của câu hỏi) là thư mục chứa tệp hình ảnh của chương trình (tệp ~ .exe) và ' thư mục làm việc hiện tại ' là thư mục, được tự động hoàn thành nếu chương trình sử dụng các đường dẫn tương đối?
colemik

3
Khi bạn #include <windows.h>, Windows sẽ tự động đặt một char*đường dẫn thực thi vào _pgmptr. Bạn không cần phải gọi thêm chức năng hoặc giả sử rác nếu bạn chỉ làm việc trên Windows.
rsethc

1
Mặc dù nhận xét là từ ba năm trước, tôi muốn mở rộng về nhận xét của rsethc _pgmptr. Tài liệu MSDN nói rằng các biến _pgmptr_wpgmptrbiến không được dùng nữa và bạn nên sử dụng hàm _get_pgmptr(char**)hoặc _get_wpgmptr(wchar_t**)thay vào đó. MSDN
Hydranix

Câu trả lời:


181

Đây là mã để có được đường dẫn đầy đủ đến ứng dụng thực thi:

Các cửa sổ:

int bytes = GetModuleFileName(NULL, pBuf, len);
return bytes ? bytes : -1;

Linux:

int bytes = MIN(readlink("/proc/self/exe", pBuf, len), len - 1);
if(bytes >= 0)
    pBuf[bytes] = '\0';
return bytes;

3
Tôi nghĩ rằng đây là câu trả lời duy nhất ở đây trả lời câu hỏi và làm như vậy cho cả Windows và Linux. Công việc tốt.
Frank Szczerba

6
Boo cho / Proc / pid / exe - Không được hỗ trợ trên OS X vì một số lý do.
Chris Lutz

24
Khi tôi nhìn thấy mã mà nhìn vào /procmột phần của tôi chết một chút. Tất cả thế giới không phải là Linux, và thậm chí trên một nền tảng đó /procnên được coi là đối tượng để thay đổi từ phiên bản này sang phiên bản khác, vòm sang vòm, v.v.
asveikau

4
nếu họ khởi chạy bằng lệnh bí danh trên Linux là argv [0] là "tên của lệnh" hay được mở rộng?
Andy Dent

20
Làm thế nào về thêm char pBuf[256]; size_t len = sizeof(pBuf);để cho giải pháp rõ ràng hơn.
charles.cc.hsu

166

Nếu bạn tìm nạp thư mục hiện tại khi chương trình của bạn bắt đầu, thì bạn thực sự có thư mục mà chương trình của bạn được bắt đầu từ đó. Lưu trữ giá trị trong một biến và tham khảo nó sau trong chương trình của bạn. Điều này khác với thư mục chứa tệp chương trình thực thi hiện tại . Nó không nhất thiết phải cùng một thư mục; nếu ai đó chạy chương trình từ một dấu nhắc lệnh, thì chương trình đang được chạy từ thư mục làm việc hiện tại của dấu nhắc lệnh mặc dù tệp chương trình nằm ở nơi khác.

getcwd là một chức năng POSIX và được hỗ trợ ngoài tất cả các nền tảng tuân thủ POSIX. Bạn sẽ không phải làm bất cứ điều gì đặc biệt (ngoài việc bao gồm các tiêu đề đúng unistd.h trên Unix và direct.h trên windows).

Vì bạn đang tạo chương trình C, nó sẽ liên kết với thư viện thời gian chạy c mặc định được liên kết bởi TẤT CẢ các quy trình trong hệ thống (tránh các trường hợp ngoại lệ được chế tạo đặc biệt) và nó sẽ bao gồm chức năng này theo mặc định. CRT không bao giờ được coi là một thư viện bên ngoài vì nó cung cấp giao diện tuân thủ tiêu chuẩn cơ bản cho HĐH.

Trên cửa sổ, chức năng getcwd không được dùng cho _getcwd. Tôi nghĩ bạn có thể sử dụng nó trong thời trang này.

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

44
Câu trả lời tốt, nhưng tôi nghĩ "thư mục làm việc hiện tại" không phải là điều mong muốn.
Michael Burr

4
bạn nên thêm rằng ngay cả khi một số tài liệu nói rằng cC Hiện tại có thể là null và sẽ được phân bổ bởi getcwd getcwd dường như không phân bổ một cái gì đó trên Mac OS và lặng lẽ làm hỏng chương trình của bạn
Janusz

4
Có một lỗi nhỏ, nhưng tiếc là tôi chưa thể chỉnh sửa .. dòng 10: cC Hiện tại: nên là cCienPath
Lipis

8
IMO trên Windows các chức năng có tên POSIXy (một số trong số đó bắt đầu bằng dấu gạch dưới) thường nên tránh. Chúng không phải là API Windows thực sự mà là CRT. API Windows mà bạn muốn sử dụng là GetCienDirectory (). msdn.microsoft.com/en-us/l
Library / aa364934 (VS85) .aspx

6
Câu trả lời của Mike là chính xác. "Thư mục hiện tại" không phải lúc nào cũng giống như thư mục mà tệp nhị phân đang chạy. Ví dụ: nếu một ứng dụng chạy như một dịch vụ trên Windows, thư mục hiện tại có thể sẽ là C: \ Windows \ System32, trong khi thư mục nhị phân thì khác.
Lucky Luke

42

Đây là từ diễn đàn cplusplus

Trên cửa sổ:

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

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

Trên 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 );
}

Trên 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 );
}

1
Giải pháp Windows đó sẽ không xử lý các ký tự không phải ANSI trong đường dẫn. Bạn có thể nên sử dụng GetModuleFileNameW và chuyển đổi nó thành UTF-8 một cách rõ ràng (cẩn thận để chuyển đổi lại bất cứ khi nào bạn cần đưa ra lệnh hệ thống tập tin).
Adrian McCarthy

3
Đối với giải pháp Windows, tôi gặp lỗi error: cannot convert 'char*' to 'LPWCH {aka wchar_t*}' for argument '2' to 'DWORD GetModuleFileNameW(HMODULE, LPWCH, DWORD)'khi biên dịch với MinGW.
HelloGoodbye

2
@Adrian, Tôi thường không phải là một lập trình viên Windows, nhưng không có DEFINE hoặc bằng cách nào đó để nói với trình biên dịch của bạn sử dụng hương vị _W () của các hàm một cách tự động?
Bạch tuộc

1
@Octopus: Để sử dụng các cuộc gọi rộng, bạn cần sử dụng WCHAR (thay vì char) và std :: wopes (thay vì std :: string).
Adrian McCarthy

29

Nếu bạn muốn một cách tiêu chuẩn mà không có thư viện: Không. Toàn bộ khái niệm về một thư mục không được bao gồm trong tiêu chuẩn.

Nếu bạn đồng ý rằng một số phụ thuộc (di động) vào lib gần tiêu chuẩn là ổn: Sử dụng thư viện hệ thống tập tin của Boost và yêu cầu init_path () .

IMHO gần như bạn có thể nhận được, với nghiệp tốt (Boost là một bộ thư viện chất lượng cao được thiết lập tốt)


8
Từ các tài liệu Boost: template <class Path> const Path & init_path (); Trả về: current_path () tại thời điểm nhập vào main (). Và current_path () là 'như thể bởi POSIX getcwd ()'. Đây không phải là những gì người hỏi yêu cầu.
Jonathan Leffler


Như đã nhận xét, điều này đưa ra đường dẫn từ nơi nhị phân được gọi, không phải đường dẫn đến nhị phân ... vì nó có thể được bắt đầu từ một thư mục khác.
jpo38

21

Filesystem TS hiện là một tiêu chuẩn (và được hỗ trợ bởi gcc 5.3+ và clang 3.9+), vì vậy bạn có thể sử dụng current_path()chức năng từ nó:

std::string path = std::experimental::filesystem::current_path();

Trong gcc (5.3+) để bao gồm Hệ thống tệp bạn cần sử dụng:

#include <experimental/filesystem>

và liên kết mã của bạn với -lstdc++fscờ.

Nếu bạn muốn sử dụng Filesystem với Microsoft Visual Studio, thì hãy đọc nó .


6
Từ liên kết được tham chiếu, 1-2) Returns the absolute path of the current working directory, obtained as if by POSIX getcwd. (2) returns path() if error occurs. Downvote, vì OP đặc biệt hỏi về đường dẫn hiện tại của tệp thực thi thay vì thư mục làm việc hiện tại.
S. Saad

20

Tôi biết rằng rất muộn trong ngày để đưa ra câu trả lời cho câu hỏi này nhưng tôi thấy rằng không có câu trả lời nào hữu ích cho tôi như giải pháp của riêng tôi. Một cách rất đơn giản để có được đường dẫn từ CWD đến thư mục bin của bạn như sau:

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

Bây giờ bạn có thể chỉ sử dụng điều này như là một cơ sở cho đường dẫn tương đối của bạn. Vì vậy, ví dụ tôi có cấu trúc thư mục này:

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

và tôi muốn biên dịch mã nguồn của mình thành bin và viết nhật ký để kiểm tra Tôi chỉ có thể thêm dòng này vào mã của mình.

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

Tôi đã thử cách tiếp cận này trên Linux bằng cách sử dụng đường dẫn đầy đủ, bí danh, v.v. và nó hoạt động tốt.

GHI CHÚ:

Nếu bạn đang ở trên windows, bạn nên sử dụng '\' làm dấu tách tệp không '/'. Bạn cũng sẽ phải thoát khỏi điều này chẳng hạn:

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

Tôi nghĩ rằng điều này sẽ làm việc nhưng chưa được thử nghiệm, vì vậy bình luận sẽ được đánh giá cao nếu nó hoạt động hoặc sửa chữa nếu không.


Vâng, nó cũng hoạt động trên Windows. Tôi nghĩ đó là giải pháp tốt nhất. Theo như tôi biết thì argv [0] luôn giữ đường dẫn đến tệp thực thi.
Wodzu

4
argv[0]là một ý tưởng rất hay, nhưng thật đáng tiếc những gì tôi nhận được trên Linux là "./my_executable_name" hoặc "./make/my_executable_name". Về cơ bản những gì tôi nhận được phụ thuộc hoàn toàn vào cách tôi khởi chạy nó
Xeverous

@Xeverous: vậy thì sao? Nếu tôi có một số tệp liên quan đến tệp thực thi của mình mà nó cần mở, bắt đầu từ "./" hoặc "./make/" trong trường hợp của bạn sẽ hoạt động. "." là thư mục làm việc hiện tại và argv [0] sẽ cho bạn biết đường dẫn tương đối đến tệp thực thi từ đó, đó chính xác là những gì OP cần. Đó là trong mọi trường hợp chính xác những gì tôi cần.
nilo

9

Không, không có cách tiêu chuẩn. Tôi tin rằng các tiêu chuẩn C / C ++ thậm chí không xem xét sự tồn tại của các thư mục (hoặc các tổ chức hệ thống tệp khác).

Trên Windows, GetModuleFileName () sẽ trả về đường dẫn đầy đủ đến tệp thực thi của quy trình hiện tại khi tham số hModule được đặt thành NULL . Tôi không thể giúp với Linux.

Ngoài ra, bạn nên làm rõ xem bạn muốn thư mục hiện tại hoặc thư mục mà hình ảnh chương trình / thực thi cư trú. Vì nó đứng câu hỏi của bạn là một chút mơ hồ về điểm này.


9

Trên Windows, cách đơn giản nhất là sử dụng _get_pgmptrhàm trong stdlib.hđể đưa con trỏ tới một chuỗi biểu thị đường dẫn tuyệt đối đến tệp thực thi, bao gồm cả tên thực thi.

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

8

Có thể nối thư mục làm việc hiện tại với argv [0]? Tôi không chắc nếu nó hoạt động trong Windows nhưng nó hoạt động trong linux.

Ví dụ:

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

Khi chạy, nó xuất ra:

jeremy @ jeremy-desktop: ~ / Desktop $ ./test
/home/jeremy/Desktop/./test


Bạn sẽ cần kiểm tra xem liệu một đường dẫn tuyệt đối được đưa ra trong argv [0]. Nhưng quan trọng hơn, điều gì sẽ xảy ra nếu hình ảnh được định vị thông qua PATH? Liệu linux có điền vào đường dẫn đầy đủ hay chỉ những gì trên dòng lệnh?
Michael Burr

Như Mike B đã chỉ ra, đó là một giải pháp không chung chung; nó chỉ hoạt động trong một số trường hợp rất hạn chế. Về cơ bản, chỉ khi bạn chạy lệnh theo tên đường dẫn tương đối - và nó không thanh lịch khi bạn chạy ../../../bin/progname thay vì ./test
Jonathan Leffler

Nếu bạn giải quyết đường dẫn tương đối có thể có của argv [0] so với thư mục hiện tại (vì argv [0] có thể là "../../myprogram.exe"), đó có lẽ là cách an toàn nhất để trả lời câu hỏi. Nó sẽ luôn hoạt động và có thể mang theo được (thậm chí nó còn hoạt động trên Android!).
jpo38


6

Bạn không thể sử dụng argv [0] cho mục đích đó, thông thường nó không chứa đường dẫn đầy đủ đến thực thi, nhưng không nhất thiết - quá trình có thể được tạo với giá trị tùy ý trong trường.

Cũng lưu ý bạn, thư mục hiện tại và thư mục có khả năng thực thi là hai thứ khác nhau, vì vậy getcwd () sẽ không giúp bạn.

Trên Windows, sử dụng GetModuleFileName (), trên các tệp đọc / dev / Proc / ProcID / .. của Linux .


3

Chỉ cần muộn màng ở đây, ...

không có giải pháp chuẩn, bởi vì các ngôn ngữ là bất khả tri của các hệ thống tệp cơ bản, vì vậy như những người khác đã nói, khái niệm hệ thống tệp dựa trên thư mục nằm ngoài phạm vi của ngôn ngữ c / c ++.

trên hết, bạn muốn không phải là thư mục làm việc hiện tại, mà là thư mục mà chương trình đang chạy, phải xem xét chương trình đã đến nơi như thế nào - tức là nó được sinh ra như một tiến trình mới thông qua một ngã ba, v.v. Để có được thư mục, một chương trình đang chạy, như các giải pháp đã chứng minh, đòi hỏi bạn phải lấy thông tin đó từ các cấu trúc điều khiển quá trình của hệ điều hành được đề cập, đây là cơ quan duy nhất cho câu hỏi này. Do đó, theo định nghĩa, nó là một giải pháp cụ thể cho hệ điều hành.


3

Đối với hệ thống Windows tại bàn điều khiển, bạn có thể sử dụng dirlệnh system ( ). Và giao diện điều khiển cung cấp cho bạn thông tin về thư mục và vv Đọc về dirlệnh tại cmd. Nhưng đối với các hệ thống giống Unix, tôi không biết ... Nếu lệnh này được chạy, hãy đọc lệnh bash. lskhông hiển thị thư mục ...

Thí dụ:

int main()
{
    system("dir");
    system("pause"); //this wait for Enter-key-press;
    return 0;
}

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

1

Trên nền tảng POSIX, bạn có thể sử dụng getcwd () .

Trên Windows, bạn có thể sử dụng _getcwd () , vì việc sử dụng getcwd () đã không được chấp nhận.

Đối với các thư viện tiêu chuẩn, nếu Boost đủ tiêu chuẩn cho bạn, tôi sẽ đề xuất Boost :: filesystem, nhưng dường như họ đã loại bỏ đường chuẩn hóa khỏi đề xuất. Bạn có thể phải đợi cho đến khi TR2 sẵn sàng cho một giải pháp hoàn toàn tiêu chuẩn.


10
getcwd () không làm những gì người hỏi đã hỏi.
Jonathan Leffler

không phải là câu trả lời được chấp nhận sử dụng getcwd () hay tôi không chỉ hiểu?
Sнаđошƒаӽ

Tôi đánh giá cao bởi vì bạn là người đi kèm với những gì được coi là câu trả lời chính xác đầu tiên.
Arnaud

Câu trả lời này thậm chí không cố gắng giải quyết câu hỏi. Xấu hổ khi viết nó.
HelloWorld

1

Đối với các đường dẫn tương đối, đây là những gì tôi đã làm. Tôi nhận thức được độ tuổi của câu hỏi này, tôi chỉ đơn giản muốn đóng góp một câu trả lời đơn giản hơn, hoạt động trong phần lớn các trường hợp:

Nói rằng bạn có một con đường như thế này:

"path/to/file/folder"

Vì một số lý do, các tệp thực thi do Linux tạo ra trong nhật thực hoạt động tốt với điều này. Tuy nhiên, các cửa sổ sẽ rất bối rối nếu được cung cấp một đường dẫn như thế này để làm việc!

Như đã nêu ở trên, có một số cách để có được đường dẫn hiện tại đến tệp thực thi, nhưng cách dễ nhất tôi thấy có tác dụng quyến rũ trong phần lớn các trường hợp là nối nó vào FRONT của đường dẫn của bạn:

"./path/to/file/folder"

Chỉ cần thêm "./" sẽ giúp bạn sắp xếp! :) Sau đó, bạn có thể bắt đầu tải từ bất kỳ thư mục nào bạn muốn, miễn là nó có thể thực thi được.

EDIT: Điều này sẽ không hoạt động nếu bạn cố khởi chạy tệp thực thi từ mã :: khối nếu đó là môi trường phát triển đang được sử dụng, vì một số lý do, mã :: khối không tải công cụ đúng ...: D

EDIT2: Một số điều mới tôi đã tìm thấy là nếu bạn chỉ định một đường dẫn tĩnh như thế này trong mã của bạn (Giả sử ví dụ.data là thứ bạn cần tải):

"resources/Example.data"

Nếu sau đó bạn khởi chạy ứng dụng của mình từ thư mục thực tế (hoặc trong Windows, bạn tạo một lối tắt và đặt thư mục hoạt động thành thư mục ứng dụng của bạn) thì nó sẽ hoạt động như vậy. Hãy ghi nhớ điều này khi gỡ lỗi các vấn đề liên quan đến đường dẫn tài nguyên / tệp bị thiếu. (Đặc biệt là trong các IDE đặt thư mục hoạt động sai khi khởi chạy bản dựng exe từ IDE)


1

Một giải pháp thư viện (mặc dù tôi biết điều này không được yêu cầu). Nếu bạn tình cờ sử dụng Qt: QCoreApplication::applicationDirPath()


1

Chỉ hai xu của tôi, nhưng mã sau đây không hoạt động được trong C ++ 17?

#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;

int main(int argc, char* argv[])
{
    std::cout << "Path is " << fs::path(argv[0]).parent_path() << '\n';
}

Có vẻ như để làm việc cho tôi trên Linux ít nhất.

Dựa trên ý tưởng trước đó, bây giờ tôi có:

std::filesystem::path prepend_exe_path(const std::string& filename, const std::string& exe_path = "");

Với việc thực hiện:

fs::path prepend_exe_path(const std::string& filename, const std::string& exe_path)
{
    static auto exe_parent_path = fs::path(exe_path).parent_path();
    return exe_parent_path / filename;
}

Và thủ thuật khởi tạo trong main():

(void) prepend_exe_path("", argv[0]);

Cảm ơn @Sam Redway cho ý tưởng argv [0]. Và tất nhiên, tôi hiểu rằng C ++ 17 đã không tồn tại trong nhiều năm khi OP đặt câu hỏi.


0

Boost Filesystem initial_path()hoạt động giống như POSIX getcwd(), và không phải những gì bạn muốn, nhưng việc thêm argv[0]vào một trong hai sẽ làm điều đó.

Bạn có thể lưu ý rằng kết quả không phải lúc nào cũng đẹp - bạn có thể nhận được những thứ như /foo/bar/../../baz/a.outhoặc /foo/bar//baz/a.out, nhưng tôi tin rằng nó luôn dẫn đến một đường dẫn hợp lệ có tên là thực thi (lưu ý rằng các dấu gạch chéo liên tiếp trong một đường dẫn được thu gọn thành một).

Trước đây tôi đã viết một giải pháp bằng cách sử dụng envp(đối số thứ ba main()hoạt động trên Linux nhưng dường như không thể thực hiện được trên Windows, vì vậy về cơ bản tôi đề xuất giải pháp tương tự như người khác đã làm trước đây, nhưng với lời giải thích bổ sung về lý do tại sao nó thực sự đúng ngay cả khi kết quả không đẹp.


0

Như Minok đã đề cập, không có chức năng nào được chỉ định theo tiêu chuẩn ini C hoặc tiêu chuẩn C ++. Đây được coi là tính năng hoàn toàn dành riêng cho hệ điều hành và được chỉ định trong tiêu chuẩn POSIX.

Thorsten79 đã đưa ra gợi ý tốt, đó là thư viện Boost.Filesystem. Tuy nhiên, nó có thể bất tiện trong trường hợp bạn không muốn có bất kỳ phụ thuộc thời gian liên kết nào ở dạng nhị phân cho chương trình của mình.

Một lựa chọn tốt khác tôi muốn giới thiệu là bộ sưu tập Thư viện STLSoft C ++ chỉ dành cho 100% tiêu đề Matthew Wilson (tác giả của những cuốn sách phải đọc về C ++). Có nền tảng di động PlatformSTL cung cấp quyền truy cập vào API dành riêng cho hệ thống: WinSTL cho Windows và UnixSTL trên Unix, vì vậy đây là giải pháp di động. Tất cả các yếu tố dành riêng cho hệ thống được chỉ định với việc sử dụng các đặc điểm và chính sách, vì vậy nó là khung mở rộng. Có thư viện hệ thống tập tin được cung cấp, tất nhiên.


0

Lệnh bash linux mà progname sẽ báo cáo một đường dẫn đến chương trình.

Ngay cả khi ai đó có thể đưa ra lệnh nào từ bên trong chương trình của bạn và hướng đầu ra tới tệp tmp và chương trình sau đó đọc tệp tmp đó, nó sẽ không cho bạn biết nếu chương trình đó là chương trình thực thi. Nó chỉ cho bạn biết nơi một chương trình có tên đó được đặt.

Những gì được yêu cầu là để có được số id tiến trình của bạn và phân tích đường dẫn đến tên

Trong chương trình của tôi, tôi muốn biết chương trình được thực thi từ thư mục bin của người dùng hay từ người khác trong đường dẫn hoặc từ / usr / bin. / usr / bin sẽ chứa phiên bản được hỗ trợ. Cảm giác của tôi là trong Linux có một giải pháp di động.


0

Sử dụng realpath()trong stdlib.hnhư thế này:

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

0

Hoạt động với việc bắt đầu từ C ++ 11, sử dụng hệ thống tệp thử nghiệm và C ++ 14-C ++ 17 cũng như sử dụng hệ thống tệp chính thức.

ứng dụng.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();

ứng dụng.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
}

Câu trả lời hay, nhưng đó là hành vi không xác định để thêm khai báo hoặc định nghĩa vào không gian tênstd . Để tránh điều này, bạn có thể thêm cả không gian tên std::filesystemvà không gian tên std::experimental::filesystemthứ ba mà bạn chọn, hoặc chỉ sử dụng using std::filesystem::path, nếu bạn không phiền khi thêm khai báo pathvào không gian tên toàn cục.
Cássio Renan

Tôi đoán sau khi C ++ 14 thử nghiệm :: hệ thống tập tin không được sử dụng nữa, vì vậy bạn có thể quên điều này? (đi vào chi nhánh #if đầu tiên)
TarmoPikaro
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.