Existe um método independente de plataforma e independente de sistema de arquivos para obter o caminho completo do diretório de onde um programa está sendo executado usando C / C ++? Não deve ser confundido com o diretório de trabalho atual. (Por favor, não sugira bibliotecas, a menos que sejam padrão, como clib ou STL.)
(Se não houver um método independente de plataforma / sistema de arquivos, sugestões que funcionem no Windows e Linux para sistemas de arquivos específicos também são bem-vindas.)
c++
c
working-directory
Ashwin Nanjappa
fonte
fonte
argv[0]
, a técnica dependerá muito do sistema operacional.#include <windows.h>
, o Windows coloca automaticamente umchar*
no caminho do executável_pgmptr
. Você não precisa chamar funções extras ou assumir que não há lixo se estiver trabalhando apenas no Windows._pgmptr
. A documentação do MSDN afirma que as variáveis_pgmptr
e_wpgmptr
estão obsoletas e você deve usar a função_get_pgmptr(char**)
ou_get_wpgmptr(wchar_t**)
não. MSDNRespostas:
Aqui está o código para obter o caminho completo para o aplicativo em execução:
Janelas:
Linux:
fonte
/proc
parte de mim morre um pouco. Todo o mundo não é o Linux, e até mesmo em que uma plataforma/proc
devem ser considerados sujeitos a mudança de versão para versão, arco de arco, etc.char pBuf[256]; size_t len = sizeof(pBuf);
para deixar a solução mais claramente.Se você buscar o diretório atual quando o programa for iniciado pela primeira vez, terá efetivamente o diretório do qual o programa foi iniciado. Armazene o valor em uma variável e consulte-o posteriormente no seu programa. Isso é diferente do diretório que contém o arquivo de programa executável atual . Não é necessariamente o mesmo diretório; se alguém executa o programa em um prompt de comando, o programa está sendo executado no diretório de trabalho atual do prompt de comando, mesmo que o arquivo do programa esteja em outro local.
getcwd é uma função POSIX e é suportada imediatamente por todas as plataformas compatíveis com POSIX. Você não precisaria fazer nada de especial (além de incluir os cabeçalhos corretos unistd.h no Unix e direct.h no Windows).
Como você está criando um programa C, ele será vinculado à biblioteca de tempo de execução c padrão, vinculada a TODOS os processos no sistema (exceções especialmente criadas, evitadas) e incluirá essa função por padrão. A CRT nunca é considerada uma biblioteca externa, pois fornece a interface compatível com o padrão básico para o sistema operacional.
No Windows, a função getcwd foi preterida em favor do _getcwd. Eu acho que você poderia usá-lo dessa maneira.
fonte
Isto é do fórum cplusplus
No Windows:
No Linux:
No HP-UX:
fonte
error: cannot convert 'char*' to 'LPWCH {aka wchar_t*}' for argument '2' to 'DWORD GetModuleFileNameW(HMODULE, LPWCH, DWORD)'
ao compilar com o MinGW.Se você deseja um caminho padrão sem bibliotecas: Não. Todo o conceito de diretório não está incluído no padrão.
Se você concorda que alguma dependência (portátil) de uma lib quase padrão está correta: Use a biblioteca do sistema de arquivos do Boost e solicite o initial_path () .
IMHO que é o mais próximo possível, com bom karma (o Boost é um conjunto de bibliotecas de alta qualidade bem estabelecido)
fonte
O sistema de arquivos TS agora é um padrão (e suportado pelo gcc 5.3+ e clang 3.9+), para que você possa usar a
current_path()
função:No gcc (5.3+) para incluir o sistema de arquivos, você precisa usar:
e vincule seu código a
-lstdc++fs
bandeira.Se você deseja usar o sistema de arquivos com o Microsoft Visual Studio, leia isso .
fonte
1-2) Returns the absolute path of the current working directory, obtained as if by POSIX getcwd. (2) returns path() if error occurs.
Downvoted, como o OP pergunta especificamente sobre o caminho atual do executável em vez do diretório de trabalho atual.Sei que é muito tarde para responder a essa pergunta, mas descobri que nenhuma das respostas era tão útil para mim quanto minha própria solução. Uma maneira muito simples de obter o caminho do seu CWD para a pasta bin é assim:
Agora você pode apenas usar isso como base para o seu caminho relativo. Então, por exemplo, eu tenho essa estrutura de diretórios:
e quero compilar meu código-fonte na lixeira e escrever um log para testar. Posso apenas adicionar essa linha ao meu código.
Eu tentei essa abordagem no Linux usando caminho completo, alias etc. e funciona muito bem.
NOTA:
Se você estiver no Windows, use um '\' como separador de arquivos, não '/'. Você terá que escapar disso também, por exemplo:
Eu acho que isso deve funcionar, mas não foi testado, portanto, o comentário seria apreciado se funcionar ou uma correção, se não.
fonte
argv[0]
é uma idéia muito boa, mas infelizmente o que estou recebendo no Linux é "./my_executable_name" ou "./make/my_executable_name". Basicamente o que eu recebo depende totalmente como eu lançá-loNão, não existe um caminho padrão. Acredito que os padrões C / C ++ nem consideram a existência de diretórios (ou outras organizações de sistemas de arquivos).
No Windows, o GetModuleFileName () retornará o caminho completo para o arquivo executável do processo atual quando o parâmetro hModule estiver definido como NULL . Eu não posso ajudar com o Linux.
Além disso, você deve esclarecer se deseja o diretório atual ou o diretório em que a imagem / executável do programa reside. Tal como está, sua pergunta é um pouco ambígua nesse ponto.fonte
No Windows, a maneira mais simples é usar a
_get_pgmptr
funçãostdlib.h
para obter um ponteiro para uma string que representa o caminho absoluto para o executável, incluindo o nome dos executáveis.fonte
Talvez concatenar o diretório de trabalho atual com argv [0]? Não tenho certeza se isso funcionaria no Windows, mas funciona no Linux.
Por exemplo:
Quando executado, gera:
fonte
Para Win32 GetCurrentDirectory deve fazer o truque.
fonte
Você não pode usar argv [0] para esse fim, geralmente ele contém o caminho completo para o executável, mas não é necessário - processo pode ser criado com um valor arbitrário no campo.
Lembre-se também de que o diretório atual e o diretório com o executável são duas coisas diferentes, portanto, getcwd () também não ajudará.
No Windows, use GetModuleFileName (), nos arquivos de leitura / dev / proc / procID / .. do Linux .
fonte
Só para empilhar atrasado aqui, ...
não há solução padrão, porque as linguagens são independentes dos sistemas de arquivos subjacentes; portanto, como outros já disseram, o conceito de sistema de arquivos baseado em diretório está fora do escopo das linguagens c / c ++.
Além disso, você não deseja o diretório de trabalho atual, mas o diretório em que o programa está sendo executado, o que deve levar em conta como o programa chegou aonde está - ou seja, foi gerado como um novo processo através de um fork, etc. Para obter o diretório em que um programa está sendo executado, como as soluções demonstraram, é necessário que você obtenha essas informações das estruturas de controle de processo do sistema operacional em questão, que é a única autoridade nessa questão. Assim, por definição, é uma solução específica para o SO.
fonte
Para o sistema Windows no console, você pode usar o
dir
comando system ( ). E o console fornece informações sobre diretório e etc. Leia sobre odir
comando emcmd
. Mas para sistemas tipo Unix, não sei ... Se esse comando for executado, leia o comando bash.ls
não exibe o diretório ...Exemplo:
fonte
fonte
Nas plataformas POSIX, você pode usar getcwd () .
No Windows, você pode usar _getcwd () , como o uso de getcwd () foi preterido.
Para bibliotecas padrão, se o Boost fosse padrão o suficiente para você, eu sugeriria o sistema de arquivos Boost ::, mas eles parecem ter removido a normalização do caminho da proposta. Você pode ter que esperar até que o TR2 esteja prontamente disponível para uma solução totalmente padrão.
fonte
Para caminhos relativos, aqui está o que eu fiz. Estou ciente da idade dessa pergunta. Quero apenas contribuir com uma resposta mais simples que funcione na maioria dos casos:
Digamos que você tenha um caminho como este:
Por alguma razão, os executáveis construídos no Linux e criados no eclipse funcionam bem com isso. No entanto, o Windows fica muito confuso se for fornecido um caminho como este para trabalhar!
Como mencionado acima, existem várias maneiras de obter o caminho atual para o executável, mas a maneira mais fácil que eu acho interessante funciona na maioria dos casos, é anexá-lo à FRENTE do seu caminho:
Basta adicionar "./" para classificar! :) Então você pode começar a carregar a partir de qualquer diretório que desejar, desde que seja com o próprio executável.
EDIT: Isso não funcionará se você tentar iniciar o executável a partir do code :: blocks se esse for o ambiente de desenvolvimento que está sendo usado, pois, por alguma razão, o code :: blocks não carrega as coisas corretamente ...: D
EDIT2: Algumas coisas novas que descobri é que, se você especificar um caminho estático como este em seu código (supondo Example.data é algo que você precisa carregar):
Se você iniciar o aplicativo a partir do diretório real (ou no Windows, criar um atalho e definir o diretório de trabalho como o diretório do aplicativo), ele funcionará dessa maneira. Lembre-se disso ao depurar problemas relacionados a caminhos de recursos / arquivos ausentes. (Especialmente nos IDEs que definem o diretório de trabalho errado ao iniciar um exe de compilação a partir do IDE)
fonte
Uma solução de biblioteca (embora eu saiba que isso não foi solicitado). Se você usa o Qt:
QCoreApplication::applicationDirPath()
fonte
Apenas meus dois centavos, mas o código a seguir não funciona de maneira portável no C ++ 17?
Parece funcionar para mim no Linux, pelo menos.
Com base na ideia anterior, agora tenho:
Com implementação:
E truque de inicialização em
main()
:Obrigado @ Sam Redway pela idéia argv [0]. E, claro, entendo que o C ++ 17 não existia há muitos anos quando o OP fez a pergunta.
fonte
O impulso do sistema de arquivos
initial_path()
se comporta como o POSIXgetcwd()
, e nem o que você deseja por si só, mas anexandoargv[0]
a um deles deve fazê-lo.Você pode notar que o resultado nem sempre é bonito - você pode obter coisas como
/foo/bar/../../baz/a.out
ou/foo/bar//baz/a.out
, mas acredito que sempre resulta em um caminho válido que nomeia o executável (observe que barras consecutivas em um caminho são recolhidas para um).Eu escrevi anteriormente uma solução usando
envp
(o terceiro argumento nomain()
qual funcionava no Linux, mas não parecia viável no Windows, por isso estou recomendando essencialmente a mesma solução que outra pessoa anteriormente, mas com a explicação adicional de por que ela está realmente correta mesmo que os resultados não sejam bonitos.fonte
Como Minok mencionou, não existe essa funcionalidade especificada no padrão C ou no padrão C ++. Este é considerado um recurso puramente específico do SO e é especificado no padrão POSIX, por exemplo.
Thorsten79 deu uma boa sugestão, é a biblioteca Boost.Filesystem. No entanto, pode ser inconveniente caso você não queira ter nenhuma dependência de tempo do link em formato binário para o seu programa.
Uma boa alternativa que eu recomendaria é a coleção de bibliotecas STLSoft C ++ 100% apenas para cabeçalhos, Matthew Wilson (autor de livros sobre leitura obrigatória sobre C ++). Há uma fachada portátil que PlatformSTL dá acesso à API específica do sistema: WinSTL para Windows e UnixSTL no Unix, por isso é uma solução portátil. Todos os elementos específicos do sistema são especificados com o uso de características e políticas, portanto, é uma estrutura extensível. Existe uma biblioteca do sistema de arquivos fornecida, é claro.
fonte
O comando linux bash que progname reportará um caminho para o programa.
Mesmo se alguém puder emitir o comando de dentro do seu programa e direcionar a saída para um arquivo tmp e o programa posteriormente ler esse arquivo tmp, ele não informará se esse programa é o que está sendo executado. Apenas informa onde está localizado um programa com esse nome.
O que é necessário é obter o número de identificação do processo e analisar o caminho para o nome
No meu programa, quero saber se o programa foi executado no diretório bin do usuário ou de outro no caminho ou em / usr / bin. / usr / bin conteria a versão suportada. Meu sentimento é que, no Linux, existe a única solução que é portátil.
fonte
Use
realpath()
emstdlib.h
como este:fonte
Funciona com a partir do C ++ 11, usando o sistema de arquivos experimental, e do C ++ 14-C ++ 17, bem como do sistema de arquivos oficial.
application.h:
application.cpp:
fonte
std
. Para evitar isso, você pode adicionar os espaços para nomestd::filesystem
estd::experimental::filesystem
um terceiro espaço para nome de sua escolha, ou apenas usarusing std::filesystem::path
, se não se importar em adicionar a declaraçãopath
ao espaço para nome global.