Question

Citing the manual here:

The functions dirname() and basename() break a null-terminated pathname string into directory and filename components. In the usual case, dirname() returns the string up to, but not including, the final '/', and basename() returns the component following the final '/'. Trailing '/' characters are not counted as part of the pathname.

And later on, you have this little table:

path         dirname    basename
"/usr/lib"    "/usr"    "lib"
"/usr/"       "/"       "usr"        // wat?
"usr"         "."       "usr"
"/"           "/"       "/"
"."           "."       "."
".."          "."       ".."

Why is dirname( "/usr/") returning "/" and not "/usr" ?
The sentence in the manual tells me I should get /usr as a result.
I tested the actual result in a dummy program and it behaves just like the manual says.

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

int main(int argc, char const *argv[])
{
    const char *mydir="/usr/";
    char *dummy  = strdup( mydir );
    char *dummy2 = strdup( mydir );

    char *dname = dirname( dummy );
    char *bname = basename( dummy2 );


    printf("mydir: '%s', dname: '%s', bname: '%s'\n", mydir, dname, bname);

    free( dummy );
    free( dummy2 );

    return 0;
}


$ ./test  
mydir: '/usr/', dname: '/', bname: 'usr'

Now, what I would expect would be:

path         dirname    basename
"/usr/"       "/usr"       ""        // more consistent?

So.. anybody understands what's going on here?

Was it helpful?

Solution

Trailing '/' characters are not counted as part of the pathname.

Hence "/usr/" is the same as "/usr", which might denote a file or a directory with name (directory entry named) usr in the directory /. The function dirname returns the parent directory of the path. The parent directory of /usr is /. Seems entirely consistent.

OTHER TIPS

A directory is also a file. usr is of course the basename of the file /usr. This follows the manual precisely - in /usr, the root-/ is the final / and usr is what follows it, hence is the basename.

As for /usr/ v. /usr, I suspect this is because the final / is always swallowed and this is specified somewhere else or falls under the "in the usual case" qualification. Or else /usr/// and /usr/////////// would refer to wildly different entities...

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