How to get the current directory in a C program?

359,196

Solution 1

Have you had a look at getcwd()?

#include <unistd.h>
char *getcwd(char *buf, size_t size);

Simple example:

#include <unistd.h>
#include <stdio.h>
#include <limits.h>

int main() {
   char cwd[PATH_MAX];
   if (getcwd(cwd, sizeof(cwd)) != NULL) {
       printf("Current working dir: %s\n", cwd);
   } else {
       perror("getcwd() error");
       return 1;
   }
   return 0;
}

Solution 2

Look up the man page for getcwd.

Solution 3

Although the question is tagged Unix, people also get to visit it when their target platform is Windows, and the answer for Windows is the GetCurrentDirectory() function:

DWORD WINAPI GetCurrentDirectory(
  _In_  DWORD  nBufferLength,
  _Out_ LPTSTR lpBuffer
);

These answers apply to both C and C++ code.

Link suggested by user4581301 in a comment to another question, and verified as the current top choice with a Google search 'site:microsoft.com getcurrentdirectory'.

Solution 4

#include <stdio.h>  /* defines FILENAME_MAX */
//#define WINDOWS  /* uncomment this line to use it for windows.*/
#ifdef WINDOWS
#include <direct.h>
#define GetCurrentDir _getcwd
#else
#include <unistd.h>
#define GetCurrentDir getcwd
#endif

int main(){
  char buff[FILENAME_MAX];
  GetCurrentDir( buff, FILENAME_MAX );
  printf("Current working dir: %s\n", buff);
  return 1;
}

Solution 5

Note that getcwd(3) is also available in Microsoft's libc: getcwd(3), and works the same way you'd expect.

Must link with -loldnames (oldnames.lib, which is done automatically in most cases), or use _getcwd(). The unprefixed version is unavailable under Windows RT.

Share:
359,196

Related videos on Youtube

CharlesB
Author by

CharlesB

Updated on January 13, 2022

Comments

  • CharlesB
    CharlesB over 2 years

    I'm making a C program where I need to get the directory that the program is started from. This program is written for UNIX computers. I've been looking at opendir() and telldir(), but telldir() returns a off_t (long int), so it really doesn't help me.

    How can I get the current path in a string (char array)?

  • Jonathan Leffler
    Jonathan Leffler over 15 years
    Picking the pickiest of nits, <errno.h> seems unnecessary, and the program reports success even on failure via its exit status. Otherwise, a nice example.
  • Jonathan Leffler
    Jonathan Leffler over 15 years
    Oh, and is it more conventional to use printf(...) in place of fprintf(stdout, ...)?
  • Keith Thompson
    Keith Thompson about 9 years
    @JonathanLeffler: That's not the pickiest of nits. This is: int main() should be int main(void).
  • mtk
    mtk over 8 years
    @angad teach a man to fish but atleast show him path to the lake/sea/ocean :)
  • gbtimmon
    gbtimmon over 8 years
    people recommending man to people trying to use the vastly superior search method google are out of touch.
  • Kroltan
    Kroltan about 8 years
    Code snippet: man 3 getcwd. Jokes aside, don't be anarchonistic, this post is from '08, SO conventions were different.
  • jacekmigacz
    jacekmigacz over 7 years
    I would use PATH_MAX from limits.h, instead of magic number if ~4KB on stack is not an issue.
  • Ajay Brahmakshatriya
    Ajay Brahmakshatriya almost 7 years
    @gbtimmon google is a search engine, it is not analogous to man page. It is eventually going to point to the man page.
  • Haseeb Mir
    Haseeb Mir over 5 years
    Why don't you use pre_defined macros for detecting OS like #if defined(_WIN32) || defined(_WIN64) || defined(WINDOWS)
  • bliako
    bliako over 5 years
    Still not there, your buffer should also accommodate for the string-termination byte/null, therefore the correct one is char cwd[PATH_MAX+1]. Or if you can't be bothered with buffers just char *buf=getcwd(NULL,0); and when you are done free(buf) (as of POSIX.1-2001)
  • Accountant م
    Accountant م over 5 years
    If I run the program from a cron this function will not return the directory of the program as expected.
  • Andrew Henle
    Andrew Henle over 4 years
    @bliako But still not there. PATH_MAX is not necessarily defined: "A definition of one of the symbolic constants in the following list shall be omitted from the <limits.h> header on specific implementations where the corresponding value is equal to or greater than the stated minimum, but where the value can vary depending on the file to which it is applied. The actual value supported for a specific pathname shall be provided by the pathconf() function."
  • bliako
    bliako over 4 years
    @Andrew Henle, that's why I offered the PATH_MAX-less solution.
  • DanielSchreiberMendes
    DanielSchreiberMendes about 4 years
    Shouldn't it be sizeof cwd instead of sizeof(cwd) ?
  • Liam
    Liam over 3 years
    In Linux (glibc), get_current_dir_name() is a bit more convenient (does its own malloc). I wanted to get just the directory name, not the entire path, so I did basename(get_current_dir_name()).
  • Omarito
    Omarito over 2 years
    Your second example leaks memory. I'm aware that the OS will clear all memory allocate for the process anyway in this case but think about the people that come will copy the code without paying attention this will potentially cause deep problems for them later.
  • Gulzar
    Gulzar over 2 years
    @AjayBrahmakshatriya The correct Google term is "How to get cwd in C++". If that gets a man page, the term changes to "How to get cwd in C++ Stack Overflow".
  • Andrew Henle
    Andrew Henle over 2 years
    @Liam If get_current_dir_name() does its own malloc(), basename(get_current_dir_name()) is an unfixable memory leak.
  • floydheld
    floydheld over 2 years
    It doesn't seem to me that this is c... is it? LPTSTR?
  • Jonathan Leffler
    Jonathan Leffler over 2 years
    @floydheld — It is C but it is using Microsoft Windows type names. Many of those are all upper-case letters (and numbers and underscores), in contrast to most other systems where the types are all lower-case instead (with some exceptions: FILE and DIR spring to mind in POSIX systems).
  • Jonathan Leffler
    Jonathan Leffler over 2 years
    If the code in HaseeB Mir's comment was enclosed in back-quotes, I believe it would look like: #if defined(_WIN32) || defined(_WIN64) || defined(__WINDOWS__). The bold WINDOWS strongly hints at double-underscores before and after 'WINDOWS'. However, looking at some corporate code that caters to Windows (as well as Unix) builds, I find #if defined(_WINDOWS) || defined(_WIN32) || defined(_WIN64) — YMMV.