简体   繁体   中英

How to get the path to the current file (pwd) in Linux from C?

I'd like to know if it is somehow possible to run system("pwd") on the current DIR. So for example let's have this folder structure:

example
 >test
  >>file
 >test2
  >>file3
  >>file4

And with opendir() and readdir() I'll get to file3 , and I want to use system("pwd") to get the path ..../example/test2/file3 . Is this somehow possible, or will pwd return the path to main.c all the time?

Simply opening and reading directories does not change the current working directory. However, changing directory in your program will.

for reference,

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

int main() {
    char cwd[1024];
    chdir("/path/to/change/directory/to");
    getcwd(cwd, sizeof(cwd));
    printf("Current working dir: %s\n", cwd);
}

For POSIX systems I found three solutions:

Get value from an environment variables "PWD"

#include <stdio.h>
#include <stdlib.h>

#ifdef __unix__
    #define IS_POSIX 1
#else
    #define IS_POSIX 0
#endif


int main (int argv, char **argc)
{
    if (IS_POSIX == 1) {
        puts("Path info by use environment variable PWD:");
        printf("\tWorkdir: %s\n", getenv("PWD"));
        printf("\tFilepath: %s/%s\n", getenv("PWD"), __FILE__);
    }
    return 0;
}

Result:

Path info by use environment variable PWD:
    Workdir: /media/setivolkylany/WorkDisk/Programming/Projects/c-utils
    Filepath: /media/setivolkylany/WorkDisk/Programming/Projects/c-utils/main.c

Use getcwd()

#include <stdio.h>
#include <stdlib.h>

#ifdef __unix__
    #define IS_POSIX 1
    #include <unistd.h>
#else
    #define IS_POSIX 0
#endif


int main (int argv, char **argc)
{
    if (IS_POSIX == 1) {
        char cwd[1024];
        getcwd(cwd, sizeof(cwd));
        puts("Path info by use getcwd():");
        printf("\tWorkdir: %s\n", cwd);
        printf("\tFilepath: %s/%s\n", cwd, __FILE__);
    }
    return 0;
}

Result

Path info by use getcwd():
    Workdir: /media/setivolkylany/WorkDisk/Programming/Projects/c-utils
    Filepath: /media/setivolkylany/WorkDisk/Programming/Projects/c-utils/main.c

Execute system command "pwd" and read output

#ifdef __unix__
    #define IS_POSIX 1
    #define _BSD_SOURCE
#else
    #define IS_POSIX 0
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int main (int argv, char **argc)
{
    if (IS_POSIX == 1) {
        char buffer[500];
        FILE *output;

        // read output of a command
        output = popen("/bin/pwd", "r");
        char *pwd = fgets(buffer, sizeof(buffer), output);

        // strip '\n' on ending of a line
        pwd = strtok(pwd, "\n");

        puts("Path info by execute shell command 'pwd':");
        printf("\tWorkdir: %s\n", pwd);
        printf("\tFilepath: %s/%s\n", pwd, __FILE__);
    }
    return 0;
}

Result:

Path info by execute shell command 'pwd':
    Workdir: /media/setivolkylany/WorkDisk/Programming/Projects/c-utils
    Filepath: /media/setivolkylany/WorkDisk/Programming/Projects/c-utils/main.c

You can use chdir(2) to change dir from C, then system("pwd"); will give you what ever directory you chdir 'ed to.

The C-equvivalent of the pwd -command is getcwd(3) .

When you use system(...) call with Windows and Linux it just executes one command. It is possible to do the same using file with commands (you can create it with C code), but my oppinion is, that you should use nftw() to get dirrectories and after that use opendir()/readdir().

How to not hardcode the path length with pathconf

I believe this is the correct way to do it:

#define _XOPEN_SOURCE 700
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

int main(void) {
    long n;
    char *buf;

    n = pathconf(".", _PC_PATH_MAX);
    assert(n != -1);
    buf = malloc(n * sizeof(*buf));
    assert(buf);
    if (getcwd(buf, n) == NULL) {
        perror("getcwd");
        exit(EXIT_FAILURE);
    } else {
        printf("%s\n", buf);
    }
    free(buf);
    return EXIT_SUCCESS;
}

GitHub upstream .

Compile and run:

gcc -Wall -Wextra -std=c11 -pedantic-errors  -o getcwd.out getcwd.c
./getcwd.out

POSIX describes _PC_PATH_MAX it as :

The value returned for the variable {PATH_MAX} indicates the longest relative pathname that could be given if the specified directory is the process' current working directory. A process may not always be able to generate a name that long and use it if a subdirectory in the pathname crosses into a more restrictive file system.

Tested on Ubuntu 18.10, n == 4096 in this implementation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM