I've got a pathname to a directory, most probably a string containing
an implementation specific pathname entered by the user.
(In fact, I'll start with a string containing the unix path to a
directory, but it could as well be a logical pathname).
I want to "append" **/* to it, that is, to append :wild-inferior to
the pathname directory, and put :wild into the pathname name, type and
version.
I thought of using MAKE-PATHNAME, to buil the new pathname, but how
can I get the pathname directory under a list of string representation
for sure? (PATHNAME-DIRECTORY even allows the implementation to
return anything it wants).
--
__Pascal_Bourguignon__ http://www.informatimago.com/
----------------------------------------------------------------------
Do not adjust your mind, there is a fault in reality.
Pascal Bourguignon <····@thalassa.informatimago.com> writes:
> I've got a pathname to a directory, most probably a string containing
> an implementation specific pathname entered by the user.
>
> (In fact, I'll start with a string containing the unix path to a
> directory, but it could as well be a logical pathname).
>
>
> I want to "append" **/* to it, that is, to append :wild-inferior to
:wild-inferiors
> the pathname directory, and put :wild into the pathname name, type and
> version.
>
> I thought of using MAKE-PATHNAME, to buil the new pathname, but how
> can I get the pathname directory under a list of string representation
> for sure? (PATHNAME-DIRECTORY even allows the implementation to
> return anything it wants).
I'm not sure I understand this last concern. PATHNAME-DIRECTORY has to
return the directory. What do you mean?
This problem is not trivial, but I think you're overstating the complexity.
Your task breaks down as follows...
If the user has entered a pathname, he might have entered:
1. /foo/bar <-- the name of the dir as a filename
2. /foo/bar/ <-- the name of the dir as a directory, with no name
3. /foo/bar/something <-- something in the dir
Most implementations offer a "directory-p" predicate. Find that. It will
help you screen out the last case. It may help you recognize the first case,
too.
The second case is already in the form you need, but if you have the first
case, you might need an operator such as the following. (Prefer the natively
supplied one if your implementation offers one.)
(defun pathname-as-directory (pathname)
;; No, I didn't test this. -kmp
(let ((pathname-host (pathname-host pathname :case :common))
(pathname-name (pathname-name pathname :case :common))
(pathname-type (pathname-type pathname :case :common)))
(check-type pathname-name (or string (eql :wild)))
(check-type pathname-type (member nil :unspecific))
(merge-pathnames (make-pathname :host pathname-host
:directory `(:relative ,pathname-name)
:case :common)
(make-pathname :name nil :type nil :version nil
:defaults pathname))))
Once you've got something in the format where all of the directory is really
in the directory, I think you should just be able to do what you said in
your problem description:
(merge-pathnames (make-pathname :host (pathname-host pathname :case :common)
:directory '(:relative :wild-inferiors)
:name :wild :type :wild :version :wild
:case :common)
(pathname-as-directory pathname))
Kent M Pitman <······@world.std.com> writes:
> Pascal Bourguignon <····@thalassa.informatimago.com> writes:
>
> > I've got a pathname to a directory, most probably a string containing
> > an implementation specific pathname entered by the user.
> >
> > (In fact, I'll start with a string containing the unix path to a
> > directory, but it could as well be a logical pathname).
> >
> >
> > I want to "append" **/* to it, that is, to append :wild-inferior to
>
> :wild-inferiors
>
> > the pathname directory, and put :wild into the pathname name, type and
> > version.
> >
> > I thought of using MAKE-PATHNAME, to buil the new pathname, but how
> > can I get the pathname directory under a list of string representation
> > for sure? (PATHNAME-DIRECTORY even allows the implementation to
> > return anything it wants).
>
> I'm not sure I understand this last concern. PATHNAME-DIRECTORY has to
> return the directory. What do you mean?
>
> This problem is not trivial, but I think you're overstating the complexity.
> Your task breaks down as follows...
> [...]
> Once you've got something in the format where all of the directory is really
> in the directory, I think you should just be able to do what you said in
> your problem description:
>
> (merge-pathnames (make-pathname :host (pathname-host pathname :case :common)
> :directory '(:relative :wild-inferiors)
> :name :wild :type :wild :version :wild
> :case :common)
> (pathname-as-directory pathname))
That's where the difficulty lies. I hoped to do that, but the
specifications of MERGE-PATHNAMES say:
If (pathname-directory default-pathname) is not a list or
(pathname-directory pathname) is not a list whose car is :relative,
the merged directory is (or (pathname-directory pathname)
(pathname-directory default-pathname))
Since the implementation of PATHNAME-DIRECTORY may return anything it
deems a "valid directory component", (like #<dircomponent-42>), that
may well not be a list, then we won't get the wanted behavior from
MERGE-PATHNAMES.
The question is: how, given a pathname (under whatever form), can one
obtain a list of the form (:ABSOLUTE string...) or (:RELATIVE
string...)?
A subsidiary question would be: how to get a logical pathname
namestring from a pathname? (Since the syntax of a logical pathname
namestring is specified and portable, it would then be simple enough
to parse it to get the wanted list form).
On the other hand, if I restrict myself to unix path names, I can
parse them and build the directory list myself, and abandon the lisp
paths... :-(
--
__Pascal_Bourguignon__ http://www.informatimago.com/
----------------------------------------------------------------------
Do not adjust your mind, there is a fault in reality.
Pascal Bourguignon <····@thalassa.informatimago.com> writes:
> > Once you've got something in the format where all of the directory
> > is really in the directory, I think you should just be able to do
> > what you said in your problem description:
> >
> > (merge-pathnames
> > (make-pathname
> > :host (pathname-host pathname :case :common)
> > :directory '(:relative :wild-inferiors)
> > :name :wild :type :wild :version :wild
> > :case :common)
> > (pathname-as-directory pathname))
>
> That's where the difficulty lies. I hoped to do that, but the
> specifications of MERGE-PATHNAMES say:
>
> If (pathname-directory default-pathname) is not a list or
> (pathname-directory pathname) is not a list whose car is :relative,
> the merged directory is (or (pathname-directory pathname)
> (pathname-directory default-pathname))
>
> Since the implementation of PATHNAME-DIRECTORY may return anything it
> deems a "valid directory component", (like #<dircomponent-42>), that
> may well not be a list, then we won't get the wanted behavior from
> MERGE-PATHNAMES.
Unless you're citing an implementation that does this, I think you're
just chasing shadows.
The fact is that the pathnames dir is the wost written of any of them.
It was a tangled mess and it was next on my list of chapters to untangle
when we ran out of time/funds and had to wind up the spec.
But first, to my knowledge, all implementations are quite consistent on
the point that directories are
NIL
or
:WILD [meaning (:ABSOLUTE :WILD)]
or
(:ABSOLUTE {component}* )
or
(:RELATIVE {component}* )
But regardless, I don't know of any implementation of MERGE-PATHNAMES
that doesn't correctly merge things according to what I said above.
> The question is: how, given a pathname (under whatever form), can one
> obtain a list of the form (:ABSOLUTE string...) or (:RELATIVE
> string...)?
You can't. Because NIL and :WILD are valid fillers. :WILD can be
canonicalized, but NIL is canonical. I don't know any implementation
that doesn't canonicalize :WILD as a filler, so I claim you can just
call PATHNAME-DIRECTORY to do that.
If you think this is not so in all implementations, you should cite a
specific implementation and then do a comparison with other implementations.
I don't like talking about "what might be" for stuff like this where
some simple community pressure can typically get things into line.
All the implementors want to do the "right thing". Most just don't know
what the trouble spots are.
To my knowledge, this is not, in practice, a trouble spot.
> A subsidiary question would be: how to get a logical pathname
> namestring from a pathname? (Since the syntax of a logical pathname
> namestring is specified and portable, it would then be simple enough
> to parse it to get the wanted list form).
NAMESTRING if the pathname is a logical pathname.
There is no operator defined for untranslating a physical pathname
through a set of logical pathnames. It's not something you're supposed
to ever need to do. It's not an operation we purported to say was
available. Why do you think you need this?
> On the other hand, if I restrict myself to unix path names, I can
> parse them and build the directory list myself, and abandon the lisp
> paths... :-(
IMO, this is paranoia and superstition. I routinely move between ALL
file systems using MAKE-PATHNAME and do not encounter problems. If you
use :CASE :COMMON you can move smoothly between any file system.
If there is a bug somewhere in some implementation that is confusing you,
you need to cite a specific case in a specific implementation and version
that is causing you a problem.