Существует ли платформо-независимый и файлово-независимый метод для получения полного пути к каталогу, из которого программа работает с использованием C / C ++? Не путать с текущим рабочим каталогом. (Пожалуйста, не предлагайте библиотеки, если они не стандартные, такие как clib или STL.)
(Если нет метода, независимого от платформы / файловой системы, приветствуются предложения, которые работают в Windows и Linux для конкретных файловых систем.)
c++
c
working-directory
Эшвин Нанджаппа
источник
источник
argv[0]
, метод будет сильно зависеть от ОС.#include <windows.h>
, Windows автоматически помещаетchar*
путь к исполняемому файлу в_pgmptr
. Вам не нужно вызывать дополнительные функции или предполагать ненужные, если вы работаете только в Windows._pgmptr
. MSDN документация утверждает , что_pgmptr
и_wpgmptr
переменные являются устаревшими, и вы должны использовать функцию_get_pgmptr(char**)
или_get_wpgmptr(wchar_t**)
вместо этого. MSDNОтветы:
Вот код, чтобы получить полный путь к исполняемому приложению:
Окна:
Linux:
источник
/proc
меня, он немного умирает. Весь мир - это не Linux, и даже на этой одной платформе/proc
следует рассмотреть возможность изменения от версии к версии, от арки к арке и т. Д.char pBuf[256]; size_t len = sizeof(pBuf);
чтобы дать решение более четко.Если вы извлекаете текущий каталог при первом запуске вашей программы, то вы фактически получаете каталог, из которого была запущена ваша программа. Сохраните значение в переменной и обратитесь к нему позже в вашей программе. Это отличается от каталога, в котором находится текущий исполняемый файл программы . Это не обязательно тот же каталог; если кто-то запускает программу из командной строки, то программа запускается из текущего рабочего каталога командной строки, даже если файл программы находится в другом месте.
getcwd - это функция POSIX, которая поддерживается всеми POSIX-совместимыми платформами. Вам не нужно было бы делать ничего особенного (кроме указания правильных заголовков unistd.h в Unix и direct.h в Windows).
Поскольку вы создаете программу на C, она будет связываться со стандартной библиотекой времени выполнения c, к которой привязаны ВСЕ процессы в системе (исключены специально созданные исключения), и будет включать эту функцию по умолчанию. CRT никогда не считается внешней библиотекой, поскольку она обеспечивает базовый стандартный интерфейс, совместимый с ОС.
В Windows функция getcwd устарела в пользу _getcwd. Я думаю, что вы могли бы использовать это таким образом.
источник
Это с форума cplusplus
На окнах:
В Linux:
На HP-UX:
источник
error: cannot convert 'char*' to 'LPWCH {aka wchar_t*}' for argument '2' to 'DWORD GetModuleFileNameW(HMODULE, LPWCH, DWORD)'
при компиляции с MinGW.Если вам нужен стандартный способ без библиотек: Нет. Вся концепция каталога не включена в стандарт.
Если вы согласны, что некоторая (переносимая) зависимость от почти стандартной библиотеки в порядке: используйте библиотеку файловой системы Boost и запросите initial_path () .
ИМХО, это как можно ближе, с хорошей кармой (Boost - это устоявшийся высококачественный набор библиотек)
источник
Файловая система TS теперь является стандартом (и поддерживается gcc 5.3+ и clang 3.9+), поэтому вы можете использовать
current_path()
функцию из нее:В gcc (5.3+) для включения файловой системы вам нужно использовать:
и свяжите свой код с
-lstdc++fs
флагом.Если вы хотите использовать файловую систему с Microsoft Visual Studio, прочитайте это .
источник
1-2) Returns the absolute path of the current working directory, obtained as if by POSIX getcwd. (2) returns path() if error occurs.
поскольку OP специально спрашивает о текущем пути исполняемого файла, а не о текущем рабочем каталоге.Я знаю, что уже слишком поздно, чтобы дать ответ на этот вопрос, но я обнаружил, что ни один из ответов не был настолько полезен для меня, как мое собственное решение. Очень простой способ получить путь от вашего CWD до вашей папки bin выглядит следующим образом:
Теперь вы можете просто использовать это в качестве основы для вашего относительного пути. Так, например, у меня есть эта структура каталогов:
и я хочу скомпилировать мой исходный код в bin и написать журнал для проверки, я могу просто добавить эту строку в свой код.
Я попробовал этот подход на Linux, используя полный путь, псевдоним и т. Д., И он работает просто отлично.
НОТА:
Если вы находитесь в Windows, вы должны использовать «\» в качестве разделителя файлов, а не «/». Вам тоже придется избежать этого, например:
Я думаю, что это должно работать, но не проверялось, так что комментарии будут оценены, если это работает, или исправление, если нет.
источник
argv[0]
Это очень хорошая идея, но, к сожалению, я получаю в Linux "./my_executable_name" или "./make/my_executable_name". В основном то, что я получу, полностью зависит от того, как я его запустилНет, стандартного способа нет. Я считаю, что стандарты C / C ++ даже не учитывают наличие каталогов (или других организаций файловой системы).
В Windows метод GetModuleFileName () возвращает полный путь к исполняемому файлу текущего процесса, если для параметра hModule установлено значение NULL . Я не могу помочь с Linux.
Также вы должны уточнить, хотите ли вы текущий каталог или каталог, в котором находится образ программы / исполняемый файл. В этом смысле ваш вопрос немного двусмысленен в этом вопросе.источник
В Windows самый простой способ - использовать
_get_pgmptr
функцию,stdlib.h
чтобы получить указатель на строку, которая представляет абсолютный путь к исполняемому файлу, включая имя исполняемого файла.источник
Может быть, объединить текущий рабочий каталог с argv [0]? Я не уверен, что это будет работать в Windows, но это работает в Linux.
Например:
При запуске выдает:
источник
Для Win32 GetCurrentDirectory должен сделать свое дело.
источник
Вы не можете использовать argv [0] для этой цели, обычно он содержит полный путь к исполняемому файлу, но необязательно - процесс может быть создан с произвольным значением в поле.
Также обратите внимание, что текущий каталог и каталог с исполняемым файлом - это две разные вещи, поэтому getcwd () вам тоже не поможет.
В Windows используйте GetModuleFileName (), в Linux читайте файлы / dev / proc / procID / ...
источник
Просто, чтобы запоздало навалить здесь ...
стандартного решения не существует, поскольку языки не зависят от базовых файловых систем, поэтому, как уже говорили другие, концепция файловой системы на основе каталогов выходит за рамки языков c / c ++.
Кроме того, вам нужен не текущий рабочий каталог, а каталог, в котором запускается программа, который должен учитывать, как программа попала туда, где она находится - то есть была ли она порождена как новый процесс с помощью форка и т. д. Чтобы получить каталог, в котором запущена программа, как показали решения, требуется, чтобы вы получали эту информацию из структур управления процессами рассматриваемой операционной системы, которая является единственным авторитетом в этом вопросе. Таким образом, по определению, это решение для конкретной ОС.
источник
Для системы Windows на консоли вы можете использовать
dir
команду system ( ). И консоль дает вам информацию о каталоге и т. Д. Читайте оdir
команде наcmd
. Но для Unix-подобных систем я не знаю ... Если эта команда запущена, прочитайте команду bash.ls
не отображать каталог ...Пример:
источник
источник
На платформах POSIX вы можете использовать getcwd () .
В Windows вы можете использовать _getcwd () , так как использование getcwd () устарело.
Для стандартных библиотек, если бы Boost был достаточно стандартным для вас, я бы предложил Boost :: filesystem, но, похоже, они удалили нормализацию пути из предложения. Возможно, вам придется подождать, пока TR2 не станет легко доступным для полностью стандартного решения.
источник
Для относительных путей вот что я сделал. Я знаю возраст этого вопроса, я просто хочу предложить более простой ответ, который работает в большинстве случаев:
Скажем, у вас есть такой путь:
По какой-то причине встроенные в Linux исполняемые файлы, созданные в Eclipse, прекрасно с этим работают. Тем не менее, окна становятся очень запутанными, если использовать такой путь для работы!
Как указывалось выше, есть несколько способов получить текущий путь к исполняемому файлу, но самый простой способ, который я нахожу, работает в большинстве случаев - это добавление к ПЕРЕДНЕМУ вашего пути:
Просто добавив "./", вы получите сортировку! :) Затем вы можете начать загрузку из любой директории, которую пожелаете, при условии, что она выполняется с самим исполняемым файлом.
РЕДАКТИРОВАТЬ: Это не будет работать, если вы попытаетесь запустить исполняемый файл из code :: blocks, если используется среда разработки, так как по какой-то причине code :: blocks не загружает вещи правильно ...: D
РЕДАКТИРОВАТЬ 2: Некоторые новые вещи, которые я обнаружил, заключаются в том, что если вы указываете статический путь, такой как этот, в своем коде (при условии, что вам нужно загрузить Example.data):
Если вы затем запускаете свое приложение из фактического каталога (или в Windows вы делаете ярлык и устанавливаете рабочий каталог в каталог вашего приложения), то оно будет работать так. Помните об этом при отладке проблем, связанных с отсутствующими путями к ресурсам / файлам. (Особенно в IDE, которые устанавливают неправильный рабочий каталог при запуске исполняемого файла сборки из IDE)
источник
Решение для библиотеки (хотя я знаю, что об этом не просили). Если вы используете Qt:
QCoreApplication::applicationDirPath()
источник
Просто мои два цента, но не работает ли следующий код в C ++ 17?
Кажется, у меня работает на Linux по крайней мере.
Исходя из предыдущей идеи, теперь у меня есть:
С внедрением:
И трюк инициализации в
main()
:Спасибо @Sam Redway за идею argv [0]. И, конечно, я понимаю, что C ++ 17 не существовал много лет, когда ОП задал вопрос.
источник
Повысьте файловую систему
initial_path()
ведет себя как POSIXgetcwd()
, и не делает то, что вы хотите, но добавляяargv[0]
одна из них к любой из них должно сделать это.Вы можете заметить, что результат не всегда хорош - вы можете получить такие вещи, как
/foo/bar/../../baz/a.out
или/foo/bar//baz/a.out
, но я считаю, что это всегда приводит к правильному пути с именем исполняемого файла (обратите внимание, что последовательные косые черты в пути свернуты в единицу).Ранее я писал решение, используя
envp
(третий аргумент,main()
который работал в Linux, но не казался работоспособным в Windows, поэтому я, по сути, рекомендую то же решение, что и кто-то другой ранее, но с дополнительным объяснением того, почему оно действительно правильно даже если результаты не красивые.источник
Как минок упоминал , в стандарте i C или стандарте C ++ такой функциональности нет. Это считается чисто ОС-особенностью, и это указано, например, в стандарте POSIX.
Thorsten79 дал хорошее предложение, это библиотека Boost.Filesystem. Тем не менее, это может быть неудобно, если вы не хотите иметь какие-либо зависимости времени соединения в двоичной форме для вашей программы.
Хорошая альтернатива, которую я бы порекомендовал, - это коллекция библиотек STLSoft C ++, предназначенных только для заголовков, только для заголовков. Мэтью Уилсон (автор обязательных для чтения книг о C ++). Портативный фасад PlatformSTL предоставляет доступ к системно-зависимому API: WinSTL для Windows и UnixSTL в Unix, поэтому это портативное решение. Все системные элементы определяются с использованием признаков и политик, поэтому это расширяемая структура. Конечно, есть библиотека файловой системы.
источник
Команда Linux Bash, которая Progname , сообщит путь к программе.
Даже если кто-то может выполнить команду which из вашей программы и направить вывод в файл tmp, а затем программа прочитает этот файл tmp, он не сообщит вам, выполняется ли эта программа. Он только говорит вам, где находится программа с таким именем.
Требуется получить номер вашего процесса и разобрать путь к имени.
В моей программе я хочу знать, была ли программа выполнена из каталога bin пользователя или из другого каталога по пути или из / usr / bin. / usr / bin будет содержать поддерживаемую версию. Я чувствую, что в Linux есть единственное решение, которое является переносимым.
источник
Используйте
realpath()
вstdlib.h
следующем образом:источник
Работает с C ++ 11, используя экспериментальную файловую систему, и C ++ 14-C ++ 17, а также используя официальную файловую систему.
application.h:
application.cpp:
источник
std
. Чтобы избежать этого, вы можете добавить как пространства имен, такstd::filesystem
иstd::experimental::filesystem
третье пространство имен по вашему выбору, или просто использоватьusing std::filesystem::path
, если вы не против добавить объявлениеpath
в глобальное пространство имен.