A UNIX Path Name Library for C++ - Path(C++)

The basic operations

A fundamental operation on Paths is that of catenation, denoted by the operator '/'.

       Path p1("foo");
       Path p2("bar");
       Path p3 = p1/p2;   // "foo/bar"

The Paths p1 and p2 need not be simple file names.

       Path p1("foo/bar");
       Path p2("../baz");
       Path p3 = p1/p2;   // "foo/baz"

The assignment version of catenation is also available.

       Path p;          // "."
       p /= "foo";      // "foo"
       p /= "bar/baz";  // "foo/bar/baz"
       p /= "..";       // "foo/bar"

The functions dirname and basename mimic the shell functions of the same name.

       Path p("foo/bar/baz.c");
       ... = p.dirname();      // "foo/bar"
       ... = p.basename();     // "baz.c"
       ... = p.basename(".c"); // "baz"

Using these functions, it becomes a simple matter to construct a variant of a given Path. For example, suppose we want to form the .o Path corresponding to the above .c Path p. The following constructor call does the trick:

       Path p_dot_o(p.dirname(), p.basename(".c"), ".o");
           // "foo/bar/baz.o"

The first argument specifies the dirname, the second argument the basename, and the third (optional) argument any desired extension of the resulting Path. If we want to put the .o file in the current directory instead of the directory containing the .c file, then we just say so in the constructor call.

       Path p_dot_o(".", p.basename(".c"), ".o");
           // "baz.o"

The above constructor is flexible, in that the ``basename'' specified can be an arbitrary Path. So, for example, the first call above could have been written

       Path p_dot_o("foo", "bar/baz", ".o");
           // "foo/bar/baz.o"

or even

       Path p_dot_o("foo", "bar/baz.o");  // "foo/bar/baz.o"

It is also possible to manipulate the components of a Path individually. For example, the following code sets q to be just like p, except that the second component in p is changed to the two-component Path ``luxury/yacht'':

       Path p("foo/bar/baz.c");
       List<Path> plist;
           // plist is "( foo bar baz.c )"
       plist[1] = "luxury/yacht";
           // plist is "( foo luxury/yacht baz.c )"
       Path q(plist);
           // "foo/luxury/yacht/baz.c"

It is an unpleasant fact of life that most machines put finite limits on the maximum lengths of paths and their components. For example, UNIX System V restricts components to be no longer than 14 characters. The function truncate_components can be used to truncate all the components in a Path to a specified maximum length.

       Path p("can/be/used/to/truncate/all/the/components");
           // "can/be/use/to/tru/all/the/com"

Every Path is either absolute (starts with a '/') or relative. It is an easy matter to construct an absolute Path corresponding to a given relative Path, or a relative Path corresponding to a given absolute Path. For example,

       Path p("foo");
       Path q("../bar");
       ... = p.absolute_version();
           // "/current/working/directory/foo"
       ... = q.absolute_version();
           // "/current/working/foo"
       ... = p.relative_version();
           // "foo"
       ... = q.relative_version();
           // "../bar"

Notice that ``absolutization'' and ``relativization'' are done with respect to the current working directory. If desired, relativization can be done with respect to an arbitrary directory. Absolutization can also be done with respect to an arbitrary directory, simply by catenating Paths: if q is absolute and p is relative, then q/p is the absolutization of p with respect to q.

The operation p.make_relative(q) returns the relative Path starting on directory q which represents the same file as p. For example,

       Path p("/foo/bar");
       ... = p.relative_version("/foo");         // "bar"
       ... = p.relative_version("/foo/bar/baz"); // ".."
       ... = p.relative_version("/foo/baz");     // "../bar"
       ... = p.relative_version("/blech");   // "../foo/bar"

The Path q can even itself be relative. In that case, q is first interpreted relative to the actual working directory.

       // suppose actual working directory is /foo
       Path p("/foo/bar");
       ... = p.relative_version(".");          // same
       ... = p.relative_version("bar/baz");    // as
       ... = p.relative_version("baz");        // above
       ... = p.relative_version("../blech");   // example

Next topic: The ksh ``test'' function
Previous topic: The class Path

© 2005 The SCO Group, Inc. All rights reserved.
SCO OpenServer Release 6.0.0 -- 02 June 2005