Question

I'm wondering why optarg returns an invalid path in the following case: --foo=~/.bashrc but not if I leave a space in between --foo ~/.bashrc.

And what would be the workaround so it works on both cases.

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

int main(int argc, char *argv[]) {
    int opt = 0;
    int long_index = 0;
    char *f; 
    static struct option longopt[] = { 
        {"foo", required_argument, 0,  'd' },
        {0,0,0,0}
    };  
    while ((opt = getopt_long(argc, argv,"d:", longopt, &long_index )) != -1) {
        switch (opt) {
            case 'd' : 
                printf("\n%s\n", optarg);
                f = realpath (optarg, NULL);
                if (f) printf("%s\n", f); 
                break;
            default: 
                exit(1);
        }   
    }   
    return 0;
}

Output:

$ ./a.out --foo=~/.bashrc
  ~/.bashrc

$ ./a.out --foo ~/.bashrc
  /home/user/.bashrc
Was it helpful?

Solution

It happens because the "tilde expansion" is performed by the shell: it isn't a valid path by itself. The tilde ~ is expanded as the home directory only in case it is at the beginning of a string argument, that's looks like a path. For example:

$ echo ~
/home/sigi
$ echo ~/a
/home/sigi/a
$ echo ~root/a
/root/a
$ echo ~a
~a
$ echo a/~
a/~

If you want to offer this functionality in the first case too, where the shell can't help you, or more generally the word expansions that are used by the shell, you can find all the needed information to do it yourself in this reference.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top