From: Dave Pearson
Subject: Getting at directories with DIRECTORY
Date: 
Message-ID: <slrn7o1pc4.9a.davep.news@hagbard.demon.co.uk>
I'm currently "toying" with my first Common Lisp application and have run up
against a little problem that I'm hoping someone might be able to help with.
I want to be able to construct a list of directories within a given
directory, however, I'm having trouble seeing a reliable method of doing
this.

I was looking at DIRECTORY but it soon became apparent that I was looking in
the wrong place. Reading the CLHS it would appear that DIRECTORY *might*
serve up a list of directories but this is implementation defined. Testing
with clisp and acl5 this would appear to be the case.

Any pointers in the right direction would be greatly appreciated.

-- 
Take a look in Hagbard's World: |      5x5.el - Silly little puzzle.
http://www.acemake.com/hagbard/ | binclock.el - emacs binary clock.
http://www.hagbard.demon.co.uk/ |  uptimes.el - Record emacs uptimes.
emacs software, including.......| handyurl.el - Recall lists of URLs.

From: Arthur Lemmens
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <378119B4.5E919357@simplex.nl>
Dave Pearson wrote:
> 
> I'm currently "toying" with my first Common Lisp application and have run up
> against a little problem that I'm hoping someone might be able to help with.
> I want to be able to construct a list of directories within a given
> directory, however, I'm having trouble seeing a reliable method of doing
> this.

There was a thread related to this subject a few months ago. Try DejaNews. 

I don't think there is a portable way to determine if a pathname (as 
returned by e.g. DIRECTORY) denotes a directory or something else. That 
makes it rather difficult to 'construct a list of directories within a
given directory'. 

On the other hand, probably just about every Common Lisp implementation 
has a way to do this. In Lispworks, you could use LW:FILE-DIRECTORY-P
and your function could be written as:

(defun list-directories (pathname) 
  (remove-if-not #'lw:file-directory-p (directory pathname)))
From: Dave Pearson
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <slrn7o2e1j.9a.davep.news@hagbard.demon.co.uk>
On Mon, 05 Jul 1999 22:46:44 +0200, Arthur Lemmens <·······@simplex.nl> wrote:

> Dave Pearson wrote:
>
> > I'm currently "toying" with my first Common Lisp application and have
> > run up against a little problem that I'm hoping someone might be able to
> > help with. I want to be able to construct a list of directories within a
> > given directory, however, I'm having trouble seeing a reliable method of
> > doing this.
> 
> There was a thread related to this subject a few months ago. Try DejaNews.

I recall a thread about how to detect if a pathname is a directory, I don't
recall a thread about getting a list of directories, my searches on DejaNews
prior to posting my request showed this to be true.

> I don't think there is a portable way to determine if a pathname (as
> returned by e.g. DIRECTORY) denotes a directory or something else. That
> makes it rather difficult to 'construct a list of directories within a
> given directory'.

Granted.

> On the other hand, probably just about every Common Lisp implementation
> has a way to do this. In Lispworks, you could use LW:FILE-DIRECTORY-P and
> your function could be written as:
> 
> (defun list-directories (pathname) 
>   (remove-if-not #'lw:file-directory-p (directory pathname)))

My problem isn't so much the detection of a directory, it is a portable and
reliable method of getting a full list back from DIRECTORY itself. For
example:

  (directory "*")

In ACL 5.0 (I'm running this on a Linux box) that gives me a list of all
files and directories in the current directory. In clisp it gives me a list
of all files. Looking at the CLHS this difference (if documented by the
implementation) is correct.

Now that you mention it I can see that my question was badly worded. I guess
I should be asking if there is any portable method of getting a *full* list
of the contents of a directory regardless of the type of the "things" in
there?

Thanks for the pointers.

-- 
Take a look in Hagbard's World: |   w3ng - The WWW Norton Guide reader.
http://www.acemake.com/hagbard/ |     eg - Norton Guide reader for Linux.
http://www.hagbard.demon.co.uk/ |    weg - Norton Guide reader for Windows.
Free software, including........| dgscan - DGROUP scanner for Clipper.
From: Steve Gonedes
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <m21zeld692.fsf@KludgeUnix.com>
··········@hagbard.demon.co.uk (Dave Pearson) writes:

< 
< On Mon, 05 Jul 1999 22:46:44 +0200, Arthur Lemmens <·······@simplex.nl> wrote:
< 
< > Dave Pearson wrote:
< >
< > > I'm currently "toying" with my first Common Lisp application and have
< > > run up against a little problem that I'm hoping someone might be able to
< > > help with. I want to be able to construct a list of directories within a
< > > given directory, however, I'm having trouble seeing a reliable method of
< > > doing this.
< > 
< > There was a thread related to this subject a few months ago. Try DejaNews.
< 
< I recall a thread about how to detect if a pathname is a directory, I don't
< recall a thread about getting a list of directories, my searches on DejaNews
< prior to posting my request showed this to be true.
< 
< > I don't think there is a portable way to determine if a pathname (as
< > returned by e.g. DIRECTORY) denotes a directory or something else. That
< > makes it rather difficult to 'construct a list of directories within a
< > given directory'.
< 
< Granted.
< 
< > On the other hand, probably just about every Common Lisp implementation
< > has a way to do this. In Lispworks, you could use LW:FILE-DIRECTORY-P and
< > your function could be written as:
< > 
< > (defun list-directories (pathname) 
< >   (remove-if-not #'lw:file-directory-p (directory pathname)))
< 
< My problem isn't so much the detection of a directory, it is a portable and
< reliable method of getting a full list back from DIRECTORY itself. For
< example:
< 
<   (directory "*")
< 
< In ACL 5.0 (I'm running this on a Linux box) that gives me a list of all
< files and directories in the current directory. In clisp it gives me a list
< of all files. Looking at the CLHS this difference (if documented by the
< implementation) is correct.
< 
< Now that you mention it I can see that my question was badly worded. I guess
< I should be asking if there is any portable method of getting a *full* list
< of the contents of a directory regardless of the type of the "things" in
< there?

Maybe using wild will work.

(directory (make-pathname 
  :directory :wild))

(directory #p"/**/")
From: Dave Pearson
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <slrn7o61kc.9a.davep.news@hagbard.demon.co.uk>
On 06 Jul 1999 13:42:49 -0400, Steve Gonedes <········@worldnet.att.net> wrote:

> Maybe using wild will work.
> 
> (directory (make-pathname :directory :wild))

Both clisp and acl get upset with the above. Did you mean something like:

  (directory (make-pathname :directory '(:absolute :wild)))

clisp gets upset with that:

,----
| CL-USER[14]> (directory (make-pathname :directory '(:absolute :wild)))
| 
| *** - MAKE-PATHNAME: illegal :DIRECTORY argument (:ABSOLUTE :WILD)
`----

but will work with "*":

,----
| CL-USER[4]> (directory (make-pathname :directory '(:absolute "*")))
| (#P"/scratch/opt/" #P"/rama/" #P"/scratch/" #P"/fd0/" #P"/eris/" #P"/misc/"
|   #P"/dos/" #P"/cdrom/" #P"/lib/" #P"/home/" #P"/root/" #P"/boot/" #P"/sbin/"
|   #P"/mnt/" #P"/etc/" #P"/bin/" #P"/usr/" #P"/var/" #P"/tmp/" #P"/dev/"
|   #P"/lost+found/"
| )
`----

and acl does the directory of sub-sub directories thing:

,----
| USER(3): (directory (make-pathname :directory '(:absolute "usr" :wild)))
| (#p"/usr/bin/mtools" #p"/usr/bin/unzip" #p"/usr/bin/zip"
|  #p"/usr/bin/zipnote" #p"/usr/bin/zipsplit" #p"/usr/bin/fromdos"
|  #p"/usr/bin/funzip" #p"/usr/bin/unzipsfx" #p"/usr/bin/zipgrep"
|  #p"/usr/bin/todos" ...)
`----

(note that here I did #p"/usr/*/" because acl wants to descend into the
likes of /root and it doesn't have permission).

-- 
Take a look in Hagbard's World: |   w3ng - The WWW Norton Guide reader.
http://www.acemake.com/hagbard/ |     eg - Norton Guide reader for Linux.
http://www.hagbard.demon.co.uk/ |    weg - Norton Guide reader for Windows.
Free software, including........| dgscan - DGROUP scanner for Clipper.
From: Kent M Pitman
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <sfwu2rg5tdk.fsf@world.std.com>
··········@hagbard.demon.co.uk (Dave Pearson) writes:

> Steve Gonedes <········@worldnet.att.net> wrote:
> 
> > (directory (make-pathname :directory :wild))
> 
> Both clisp and acl get upset with the above.

I think :directory :wild is supposed to work.
CLHS 19.2.2.4.3:
 "The directory might be a string, :wild, :unspecific, or nil. 
  The directory can be a list of strings and symbols.  [...]"

> Did you mean something like:
>   (directory (make-pathname :directory '(:absolute :wild)))

I think it's perhaps ambiguous whether :wild means '(:relative :wild)
or '(:absolute :wild).  I would have guessed the former, actually.
The spec does not say.  I think this was backward compatibility that
should have gone away.

> clisp gets upset with that:
 
You don't say what version.  When reporting what may potentially be a
bug, try to specify a version so that when it's fixed, this report won't
sit around as misinformation.

> ,----
> | CL-USER[14]> (directory (make-pathname :directory '(:absolute :wild)))
> | 
> | *** - MAKE-PATHNAME: illegal :DIRECTORY argument (:ABSOLUTE :WILD)
> `----

Sounds like a bug.
 
> but will work with "*":

This is permitted, but since it's less portable is not to be preferred.
 
> ,----
> | CL-USER[4]> (directory (make-pathname :directory '(:absolute "*")))
> | (#P"/scratch/opt/" #P"/rama/" #P"/scratch/" #P"/fd0/" #P"/eris/" #P"/misc/"
> |   #P"/dos/" #P"/cdrom/" #P"/lib/" #P"/home/" #P"/root/" #P"/boot/" #P"/sbin/"
> |   #P"/mnt/" #P"/etc/" #P"/bin/" #P"/usr/" #P"/var/" #P"/tmp/" #P"/dev/"
> |   #P"/lost+found/"
> | )
> `----
> 
> and acl does the directory of sub-sub directories thing:

Version?

> ,----
> | USER(3): (directory (make-pathname :directory '(:absolute "usr" :wild)))
> | (#p"/usr/bin/mtools" #p"/usr/bin/unzip" #p"/usr/bin/zip"
> |  #p"/usr/bin/zipnote" #p"/usr/bin/zipsplit" #p"/usr/bin/fromdos"
> |  #p"/usr/bin/funzip" #p"/usr/bin/unzipsfx" #p"/usr/bin/zipgrep"
> |  #p"/usr/bin/todos" ...)
> `----

Sounds like a bug.  :wild-inferiors is what's supposed to do that.
:wild is only supposed to match one level.
 
> (note that here I did #p"/usr/*/" because acl wants to descend into the
> likes of /root and it doesn't have permission).

One of many good reasons to have :wild, not :wild-inferiors, be the
default.
From: Dave Pearson
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <slrn7o8iuk.9a.davep.news@hagbard.demon.co.uk>
[Apologies for the double followup but something caught my eye]

On Wed, 7 Jul 1999 16:15:03 GMT, Kent M Pitman <······@world.std.com> wrote:

> > Did you mean something like:
> >   (directory (make-pathname :directory '(:absolute :wild)))
> 
> I think it's perhaps ambiguous whether :wild means '(:relative :wild) or
> '(:absolute :wild). I would have guessed the former, actually. The spec
> does not say. I think this was backward compatibility that should have
> gone away.

To be clear, I wasn't trying to suggest that :wild on its own would be
:absolute, I saw nothing to suggest that it would be anything other than
:relative (but as you say, there isn't anything to say that it isn't, I
guess I gave in to "common sense" at that point), I was asking if the
example the poster had in mind was to use it in an :absolute directory
specifier.

-- 
Take a look in Hagbard's World: |   w3ng - The WWW Norton Guide reader.
http://www.acemake.com/hagbard/ |     eg - Norton Guide reader for Linux.
http://www.hagbard.demon.co.uk/ |    weg - Norton Guide reader for Windows.
Free software, including........| dgscan - DGROUP scanner for Clipper.
From: Dave Pearson
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <slrn7o8ifk.9a.davep.news@hagbard.demon.co.uk>
On Wed, 7 Jul 1999 16:15:03 GMT, Kent M Pitman <······@world.std.com> wrote:
> ··········@hagbard.demon.co.uk (Dave Pearson) writes:
> 
> > Steve Gonedes <········@worldnet.att.net> wrote:
> > 
> > > (directory (make-pathname :directory :wild))
> > 
> > Both clisp and acl get upset with the above.
> 
> I think :directory :wild is supposed to work.
> CLHS 19.2.2.4.3:
>  "The directory might be a string, :wild, :unspecific, or nil. 
>   The directory can be a list of strings and symbols.  [...]"

That was my understanding.

> > clisp gets upset with that:
>  
> You don't say what version. When reporting what may potentially be a bug,
> try to specify a version so that when it's fixed, this report won't sit
> around as misinformation.

Apologies, you're right, that was laziness on my part. 

,----
| CL-USER[2]> (lisp-implementation-version) 
| "1999-01-08 (January 1999)"
`----

Now that I'm learning a little more about what should and shouldn't happen
with the pathname stuff I was going to grab the latest cut, build it and try
it and then ask about the result on the clisp mailing list.

> > ,----
> > | CL-USER[4]> (directory (make-pathname :directory '(:absolute "*")))
> > | (#P"/scratch/opt/" #P"/rama/" #P"/scratch/" #P"/fd0/" #P"/eris/" #P"/misc/"
> > |   #P"/dos/" #P"/cdrom/" #P"/lib/" #P"/home/" #P"/root/" #P"/boot/" #P"/sbin/"
> > |   #P"/mnt/" #P"/etc/" #P"/bin/" #P"/usr/" #P"/var/" #P"/tmp/" #P"/dev/"
> > |   #P"/lost+found/"
> > | )
> > `----
> > 
> > and acl does the directory of sub-sub directories thing:
> 
> Version?

Apologies for my laziness again (in this case I'd already said in the thread
what version of acl I was using but it is lazy of my to expect people to
have read and remembered all my input into this thread).

,----
| USER(8): (lisp-implementation-version)
| "5.0 [Linux/X86] (8/29/98 10:57)"
`----

Kent, thanks for the clarifications and corrections.

-- 
Take a look in Hagbard's World: |      5x5.el - Silly little puzzle.
http://www.acemake.com/hagbard/ | binclock.el - emacs binary clock.
http://www.hagbard.demon.co.uk/ |  uptimes.el - Record emacs uptimes.
emacs software, including.......| handyurl.el - Recall lists of URLs.
From: Espen Vestre
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <w6vhbv36p0.fsf@wallace.nextel.no>
Kent M Pitman <······@world.std.com> writes:

> > | USER(3): (directory (make-pathname :directory '(:absolute "usr" :wild)))
> > | (#p"/usr/bin/mtools" #p"/usr/bin/unzip" #p"/usr/bin/zip"
> > |  #p"/usr/bin/zipnote" #p"/usr/bin/zipsplit" #p"/usr/bin/fromdos"
> > |  #p"/usr/bin/funzip" #p"/usr/bin/unzipsfx" #p"/usr/bin/zipgrep"
> > |  #p"/usr/bin/todos" ...)
> > `----
> 
> Sounds like a bug.  :wild-inferiors is what's supposed to do that.
> :wild is only supposed to match one level.

The bug isn't related to :wild, it seems, but to the fact that
ACL treats pure directory pathnames as if they were WILD-PATHNAME-P
(which is consistent with familiar unix behaviour of e.g. ls) 
even though ACL itself claims it's not:

USER(47): (setf u (make-pathname :directory "/usr"))
#p"/usr/"
USER(48): (wild-pathname-p u)
NIL
USER(49): (directory u)
(#p"/usr/local" #p"/usr/ucbinclude" #p"/usr/java1.1" #p"/usr/java"
 #p"/usr/usr" #p"/usr/vmsys" #p"/usr/oasys" #p"/usr/adm" #p"/usr/4lib"
 #p"/usr/ucblib" ...)
USER(50): 

The Hyperspec says that (directory u) should return 0 or 1 elements
in its result if u is not wild.  The definition of "wild" seems to
be a bit sloppy (?), i.e. one could perhaps interpret it as allowing
implemantations to treat pure directory pathnames as being wild, 
but then wild-pathname-p should return T, shouldn't it?
-- 

  regards, Espen Vestre
From: Pekka P. Pirinen
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <ixoghnp6t3.fsf@gaspode.cam.harlequin.co.uk>
Espen Vestre <·····@nospam.vestre.net> writes:
> Kent M Pitman <······@world.std.com> writes:
> 
> > | USER(3): (directory (make-pathname :directory '(:absolute "usr" :wild)))
> > | (#p"/usr/bin/mtools" #p"/usr/bin/unzip" #p"/usr/bin/zip" [...]
> > 
> > Sounds like a bug.  :wild-inferiors is what's supposed to do that.
> > :wild is only supposed to match one level.
> 
> The bug isn't related to :wild, it seems, but to the fact that
> ACL treats pure directory pathnames as if they were WILD-PATHNAME-P
> (which is consistent with familiar unix behaviour of e.g. ls) 
> even though ACL itself claims it's not:
> 
> USER(47): (setf u (make-pathname :directory "/usr"))
> #p"/usr/"
> USER(48): (wild-pathname-p u)
> NIL
> USER(49): (directory u)
> (#p"/usr/local" #p"/usr/ucbinclude" #p"/usr/java1.1" #p"/usr/java" [...]

Yes, that's much more practical than the wierd rules/bugs of CLISP.
LispWorks has similar behaviour.

It is important to note that, according to the standard, DIRECTORY and
PATHNAME-MATCH-P must agree, so if #P"/usr/*/" matches
#P"/usr/bin/mtools" in ACL (as one would expect), DIRECTORY must
behave as it does in ACL.  Since the matching rules are
implementation-defined, code using DIRECTORY is usually not portable
in the strict sense.

Note that when investigating these matters, it is wise to use DESCRIBE
to make sure the pathnames match your expectations -- two pathnames
that look the same might have different components.

> The Hyperspec says that (directory u) should return 0 or 1 elements
> in its result if u is not wild.  The definition of "wild" seems to
> be a bit sloppy (?), i.e. one could perhaps interpret it as allowing
> implemantations to treat pure directory pathnames as being wild, 

Oh, it's quite precise, but it turns out to mean a pathname that could
match several pathnames, so that clause on DIRECTORY is tautologous.
Since a NIL value in a pathname field typically matches anything
(although this is implementation-defined), any such pathname is
wild, which doesn't make it a particularly useful term.

> but then wild-pathname-p should return T, shouldn't it?

No.  Surprisingly, WILD-PATHNAME-P does not test for the pathname
being wild, it tests for "the presence of wildcard components".

The pathname spec is hopelessly vague.  It simply doesn't go far
enough to define a useful abstraction, let alone a portable one.
-- 
Pekka P. Pirinen
Harlequin Group plc (but not for long)
"Unix is the answer, but only if you phrase the question very carefully."
                    anonymous 
From: Espen Vestre
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <w6r9miz2go.fsf@wallace.nextel.no>
·····@harlequin.co.uk (Pekka P. Pirinen) writes:

> It is important to note that, according to the standard, DIRECTORY and
> PATHNAME-MATCH-P must agree, so if #P"/usr/*/" matches
> #P"/usr/bin/mtools" in ACL (as one would expect), DIRECTORY must
> behave as it does in ACL.  Since the matching rules are
> implementation-defined, code using DIRECTORY is usually not portable
> in the strict sense.

Yes, but I wasn't talking about #p"/usr/*/", but #p"/usr/", and
the standard explicitly says that directory should return 0 or
1 elements in the list if the pathname is not _wild_.

USER(54): (setf u (make-pathname :directory "/usr"))
#p"/usr/"
USER(55): (describe u)
#p"/usr/" is a structure of type PATHNAME.  It has these slots:
 HOST               NIL
 DEVICE             :UNSPECIFIC
 DIRECTORY          (:ABSOLUTE "usr")
 NAME               NIL
 TYPE               NIL
 VERSION            :UNSPECIFIC
 NAMESTRING         NIL
 HASH               NIL
 DIR-NAMESTRING     NIL

(Actually, I've sometimes considered the behaviour of 'ls <dir>' to
 be quite annoying as well, the fact that ls acts differently on
 a file that happens to be a directory than on other files is not
 always a Good Thing)

-- 

  (espen)
From: Pekka P. Pirinen
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <ixso6xaaxi.fsf@gaspode.cam.harlequin.co.uk>
Espen Vestre <·····@nospam.vestre.net> writes:
> ·····@harlequin.co.uk (Pekka P. Pirinen) writes:
> 
> > It is important to note that, according to the standard, DIRECTORY and
> > PATHNAME-MATCH-P must agree, so if #P"/usr/*/" matches
> > #P"/usr/bin/mtools" in ACL (as one would expect), DIRECTORY must
> > behave as it does in ACL. [...]
> 
> Yes, but I wasn't talking about #p"/usr/*/", but #p"/usr/", and

Right, those pathnames were from Kent's example that you quoted.  In
either case, it matched an extra level beyond what was specified in
the directory list.

> the standard explicitly says that directory should return 0 or
> 1 elements in the list if the pathname is not _wild_.
> 
> USER(54): (setf u (make-pathname :directory "/usr"))
> #p"/usr/"
> USER(55): (describe u)
> #p"/usr/" is a structure of type PATHNAME.  It has these slots:
>  HOST               NIL
>  DEVICE             :UNSPECIFIC
>  DIRECTORY          (:ABSOLUTE "usr")
>  NAME               NIL
>  TYPE               NIL
>  VERSION            :UNSPECIFIC
>  NAMESTRING         NIL
>  HASH               NIL
>  DIR-NAMESTRING     NIL

But that pathname _is_ wild by definition, because it can match more
than one pathname.  When hacking the pathname system at Harlequin, we
assumed "match" means the same thing in the definition of "wild" as
elsewhere (PATHNAME-MATCH-P), and the reference to WILD-PATHNAME-P is
informational, rather than definitional.  Note furthermore, that
19.2.2.3 and WILD-PATHNAME-P use the term "wildcard pathname", not
"wild pathname".

The way DIRECTORY works in ACL or LispWorks is actually
practical, or at least it can be made to work in a practical and
consistent way.  In LWW 4.1:

CL-USER 1> (directory #P"/usr/")
(#P"c:/usr/local/" #P"c:/usr/dict/")
CL-USER 2> (directory #P"/usr/*")
(#P"c:/usr/local/" #P"c:/usr/dict/")
CL-USER 3> (directory #P"/usr/*/")
(#P"c:/usr/local/man/" #P"c:/usr/local/lib/" #P"c:/usr/local/info/"
 #P"c:/usr/local/emacs/" #P"c:/usr/local/congruent/"
 #P"c:/usr/local/bin/" #P"c:/usr/dict/words")

So you can match exactly one level, if you know the matching rules.
You can even match just the directory:

CL-USER 4> (directory (truename #P"/usr/"))
(#P"c:/usr/")

Unfortunately, the rules are implementation-defined with no
restrictions, and different from implementation to implementation.  It
would be better if this was more tightly specified in the standard.
-- 
Pekka P. Pirinen, language lawyer
Harlequin Group plc (but not for long)
"Truth is stranger than fiction because fiction has to make sense."
   - Steve Smith <sgs_grebyn.com>
From: Kent M Pitman
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <sfw7loa60w5.fsf@world.std.com>
Espen Vestre <·····@nospam.vestre.net> writes:

> Kent M Pitman <······@world.std.com> writes:
> 
> > > | USER(3): (directory (make-pathname :directory '(:absolute "usr" :wild)))
> > > | (#p"/usr/bin/mtools" #p"/usr/bin/unzip" #p"/usr/bin/zip"
> > > |  #p"/usr/bin/zipnote" #p"/usr/bin/zipsplit" #p"/usr/bin/fromdos"
> > > |  #p"/usr/bin/funzip" #p"/usr/bin/unzipsfx" #p"/usr/bin/zipgrep"
> > > |  #p"/usr/bin/todos" ...)
> > > `----
> > 
> > Sounds like a bug.  :wild-inferiors is what's supposed to do that.
> > :wild is only supposed to match one level.
> 
> The bug isn't related to :wild, it seems, but to the fact that
> ACL treats pure directory pathnames as if they were WILD-PATHNAME-P
> (which is consistent with familiar unix behaviour of e.g. ls) 
> even though ACL itself claims it's not:
> 
> USER(47): (setf u (make-pathname :directory "/usr"))
> #p"/usr/"
> USER(48): (wild-pathname-p u)
> NIL
> USER(49): (directory u)
> (#p"/usr/local" #p"/usr/ucbinclude" #p"/usr/java1.1" #p"/usr/java"
>  #p"/usr/usr" #p"/usr/vmsys" #p"/usr/oasys" #p"/usr/adm" #p"/usr/4lib"
>  #p"/usr/ucblib" ...)
> USER(50): 

There is some vaguery in the pathname stuff--whether enough to accomodate
this, I can't say without more work than I have time to do this moment.

But regardless of legality, I consider this a horrendous decision from
the point of view of programs trying to do the right thing portably.  It
also makes it hard to know if you have a correct program statically.

The problem is that it doesn't make the algebra consistent.  Things
that should be identities are not.

These kinds of "helpful" things seem useful when dealing with code involving
constant strings, but they greatly complicate the ability to use code
that does not know the specific name of the string it's dealing with and is
constructing it out of bits and pieces.  To see the problem, consider:

(when (directory (make-pathname
		   :name :wild 
	           :type :wild
	           :version :wild
                   :defaults (progn
                              (format t "Delete files in what directory?")
		              (parse-namestring (read-line)))))
 ... stuff you wish would be done on the predicted set of files ...)

and consider what happens if the person types "/usr/fred/junk" where
perhaps he meant "/usr/fred/junk/".

All kinds of errors can creep into code that does not contain constant
strings but rather contains variable quantities since you won't know,
in general, whether you're getting a list of the given dir or a subdir.

Of course, I'd be very happy to see the Lisp Machine's pathname-as-directory
as directory-pathname-as-file operations in CL, but...

> The Hyperspec says that (directory u) should return 0 or 1 elements
> in its result if u is not wild.  The definition of "wild" seems to
> be a bit sloppy (?), i.e. one could perhaps interpret it as allowing
> implemantations to treat pure directory pathnames as being wild, 
> but then wild-pathname-p should return T, shouldn't it?

I would think so.
From: Lyman S. Taylor
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <37810BC8.99372899@mindspring.com>
Dave Pearson wrote:

> Any pointers in the right direction would be greatly appreciated.

  The following depends upon what PROBE-FILE returns when given a directory. 
  The standard says it should be non nil on a "file".  I suppose whether  
  a directory specification, /usr/local/,  is a "file" or not is debatable. 
 [ Therefore, this may not be portable as I hope.] 

(defconstant *path-seperator* "/" )

(defun list-subdirectories (  dir-spec ) 
 "return a list of subdirectories of the given directory's pathname (e.g., '/usr/' )" 
 (labels ( (cat-path-seperator (p)
             (pathname (concatenate 'string (namestring p )
					    *path-seperator* ))) )
    (loop for file in  (directory dir-spec )
       when (probe-file (cat-path-seperator  file))
            collect file ))))


  I imagine there are more direct and nonportable solutions to this in 
  each implementation. 

  Examples [ at least on Unix :-) ]: 

     (list-subsdirectories (pathname ".") ) ==>  ... list of current directory's subdirs....

     (list-subdirectories (pathname "/usr/local/" ) ==>  ... /usr/local's  subdirs... 


  NOTE: you have to be careful not to give the name of the directory so that it looks like 
         a file 
    
      (list-subirectories (pathname "/usr/local" ) ==>  ( #p"/usr/local" ) 


----

Lyman
From: Christopher R. Barry
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <87u2riecvx.fsf@2xtreme.net>
"Lyman S. Taylor" <············@mindspring.com> writes:

>   The following depends upon what PROBE-FILE returns when given a directory. 
>   The standard says it should be non nil on a "file".  I suppose whether  
>   a directory specification, /usr/local/,  is a "file" or not is debatable. 
>  [ Therefore, this may not be portable as I hope.] 
> 
> (defconstant *path-seperator* "/" )
> 
> (defun list-subdirectories (  dir-spec ) 
>  "return a list of subdirectories of the given directory's pathname (e.g., '/usr/' )" 
>  (labels ( (cat-path-seperator (p)
>              (pathname (concatenate 'string (namestring p )
> 					    *path-seperator* ))) )
>     (loop for file in  (directory dir-spec )
>        when (probe-file (cat-path-seperator  file))
>             collect file ))))

This does not work with CLISP on Unix, nor does it even pretend to be
portable.

Christopher
From: Dave Pearson
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <slrn7o3e1b.9a.davep.news@hagbard.demon.co.uk>
On Mon, 05 Jul 1999 12:47:20 -0700, Lyman S. Taylor <············@mindspring.com> wrote:
> Dave Pearson wrote:
> 
> > Any pointers in the right direction would be greatly appreciated.
> 
>   The following depends upon what PROBE-FILE returns when given a directory. 
>   The standard says it should be non nil on a "file".  I suppose whether  
>   a directory specification, /usr/local/,  is a "file" or not is debatable. 
>  [ Therefore, this may not be portable as I hope.] 

You're right, it doesn't appear to be portable. With ACL 4.3(Linux):

,----
| USER(3): (directory (pathname "/usr/local/"))
| (#p"/usr/local/lost+found" #p"/usr/local/bin" #p"/usr/local/etc"
|  #p"/usr/local/games" #p"/usr/local/lib" #p"/usr/local/info"
|  #p"/usr/local/man" #p"/usr/local/sbin" #p"/usr/local/src"
|  #p"/usr/local/include" ...)
`----

With clisp:

,----
| CL-USER[17]> (directory (pathname "/usr/local/"))
| (#P"/usr/local/")
`----

>   I imagine there are more direct and nonportable solutions to this in
>   each implementation.

This would appear to be true, at least for the three implementations I've
got here (well, two implementations, two versions of one of them).

Thanks for the input.

-- 
Take a look in Hagbard's World: |      5x5.el - Silly little puzzle.
http://www.acemake.com/hagbard/ | binclock.el - emacs binary clock.
http://www.hagbard.demon.co.uk/ |  uptimes.el - Record emacs uptimes.
emacs software, including.......| handyurl.el - Recall lists of URLs.
From: Hartmann Schaffer
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <Ft7g3.884$j3.4907@tor-nn1.netcom.ca>
In article <························@hagbard.demon.co.uk>,
	··········@hagbard.demon.co.uk (Dave Pearson) writes:
> I'm currently "toying" with my first Common Lisp application and have run up
> against a little problem that I'm hoping someone might be able to help with.
> I want to be able to construct a list of directories within a given
> directory, however, I'm having trouble seeing a reliable method of doing
> this.

Check out the documentation of path names.  With the systems I have used 
putting a wild card as the last element of the directory section gave me 
a list of all path directories

-- 

Hartmann Schaffer

It is better to fill your days with life than your life with days
From: Dave Pearson
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <slrn7o2dd3.9a.davep.news@hagbard.demon.co.uk>
On Mon, 05 Jul 1999 19:13:41 GMT, Hartmann Schaffer <··@inferno.nirvananet> wrote:
> In article <························@hagbard.demon.co.uk>,
> 	··········@hagbard.demon.co.uk (Dave Pearson) writes:
> > I'm currently "toying" with my first Common Lisp application and have run up
> > against a little problem that I'm hoping someone might be able to help with.
> > I want to be able to construct a list of directories within a given
> > directory, however, I'm having trouble seeing a reliable method of doing
> > this.
> 
> Check out the documentation of path names. With the systems I have used
> putting a wild card as the last element of the directory section gave me a
> list of all path directories

If you're saying what I think you're saying I tried this and got different
results. I assume you're talking about something like:

  (directory #p"/*/")

With clisp I got a list of directory entries in root. With ACL 4.3 and 5.0 I
got a list of the contents of each directory off of the root.

-- 
Take a look in Hagbard's World: |   w3ng - The WWW Norton Guide reader.
http://www.acemake.com/hagbard/ |     eg - Norton Guide reader for Linux.
http://www.hagbard.demon.co.uk/ |    weg - Norton Guide reader for Windows.
Free software, including........| dgscan - DGROUP scanner for Clipper.
From: Christopher R. Barry
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <87so72ecr0.fsf@2xtreme.net>
··········@hagbard.demon.co.uk (Dave Pearson) writes:

> I'm currently "toying" with my first Common Lisp application and have run up
> against a little problem that I'm hoping someone might be able to help with.
> I want to be able to construct a list of directories within a given
> directory, however, I'm having trouble seeing a reliable method of doing
> this.
> 
> I was looking at DIRECTORY but it soon became apparent that I was looking in
> the wrong place. Reading the CLHS it would appear that DIRECTORY *might*
> serve up a list of directories but this is implementation defined. Testing
> with clisp and acl5 this would appear to be the case.

Sadly, you are correct.

There is an almost 100% portable way to list all files BUT NOT
directories in a path that designates a directory. The trick is to
portably give a valid argument to DIRECTORY to do this. The solution
is below. The only way this could fail is if an implementation uses a
syntax other than "*" to denote a :WILD name component and chooses to
return a string containing this syntax to PATHNAME-NAME instead of the
:WILD keyword. CLISP returns "*" instead of :WILD, and ANSI/X3.226
unfortunately allows this.

(defun path-as-directory-arg (path)
  "Assumes PATH is meant to designate a directory and returns it as
 a wild PATHNAME that will do the right thing when given to DIRECTORY.
 The PATHNAME returned may or may not point to a directory that actually
 exists."
  (let* ((name (pathname-name path))
	 (pathname (pathname path)))
    (if (or (eql name :WILD)		;PATHNAME-NAME of #p"/home/*" may be
	    (string= name "*"))		;either :WILD or "*"
	pathname
      (make-pathname :host (pathname-host pathname)
		     :device (pathname-device pathname)
		     :directory (if (or name ;Is name NIL?
					(< (length name) 0)) ;Is name ""?
				    (append (pathname-directory pathname)
					    (list name))
				  (pathname-directory pathname))
		     :name :wild
		     :type nil
		     :version nil))))

Any ANSI compliant Unix Lisp must behave this way:

  (path-as-directory-arg "/usr")
 => #P"/usr/*"

  (path-as-directory-arg "/usr/")
 => #P"/usr/*"

  (path-as-directory-arg "/usr/*")
 => #P"/usr/*"

This works similarly with Genera and will work with an ANSI compliant
Windows Lisp.

Now the list of paths returned from a DIRECTORY call does not have to
contain directories. CLISP has this behavior. It is unfortanate that
this is compliant with X3.226.

But lets assume every Lisp _does_ return a list containing both files
_and_ directories and you want to determine which is which. You
absolutely can not portably do this either. Look at the behavior of
PROBE-FILE in CLISP:

  [1]> (probe-file "/usr")
  *** - NAMESTRING: "/usr" names a directory, not a file

  [3]> (probe-file "/usr/")
  *** - no file name given: #P"/usr/"

and then in Allegro CL:

  USER(1): (probe-file "/usr")
  #p"/usr"

  USER(2): (probe-file "/usr/")
  #p"/usr/"

Per X3.226, both behaviors are allowable. You might also think that
you could just try a call to DIRECTORY on each path returned and see
what happens but in CLISP:

  [5]> (directory "/usr")
  *** - NAMESTRING: "/usr" names a directory, not a file

  [7]> (directory "/usr/")
  (#P"/usr/")

and in Allegro:

  USER(3): (directory "/usr")
  (#p"/usr")

  USER(4): (directory "/usr/")
  (#p"/usr/lesstif" #p"/usr/i486-linuxlibc1" #p"/usr/local" #p"/usr/X11R6"
   #p"/usr/src" #p"/usr/man" #p"/usr/info" #p"/usr/include" #p"/usr/games"
   #p"/usr/dict" ...)

I really hope J13 cleans up all this stuff. It's really sad how
crippled you are in ANSI Common Lisp when doing routine filesystem
operations compared to something like Java. (Except Java doesn't even
pretend to acknowledge versioned filesystems... but a file-chooser
widget would be required to do the right thing anyways....)

Also, I discovered a bug in Allegro CL while playing around with this
stuff:

  USER(26): (wild-pathname-p #p"/home/*")
  T

  USER(27): (probe-file #p"/home/*")
  NIL

Per the CLHS, PROBE-FILE should signal an error of type FILE-ERROR if
pathspec is wild.

Christopher
From: Dave Pearson
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <slrn7o3dm1.9a.davep.news@hagbard.demon.co.uk>
On Tue, 06 Jul 1999 02:15:20 GMT, Christopher R. Barry <······@2xtreme.net> wrote:
> ··········@hagbard.demon.co.uk (Dave Pearson) writes:
> 
> > I was looking at DIRECTORY but it soon became apparent that I was
> > looking in the wrong place. Reading the CLHS it would appear that
> > DIRECTORY *might* serve up a list of directories but this is
> > implementation defined. Testing with clisp and acl5 this would appear to
> > be the case.
> 
> Sadly, you are correct.
>
> [SNIP]

Christopher (and others), first off, many thanks for your input and
pointers. Much appreciated.

As it is, when this app gets running it'll be running with clisp so I'll
probably do something specific to the implementation. I notice that both
clisp and ACL provide some access to the likes of opendir/readdir/closedir.
I'm also mindful of the fact that this is a "just do it" solution so your
explanation of the situation is appreciated from the educational POV.

I wonder if I could indulge the group on a wider issue that this raises in
my mind? In my slow meanderings around Common Lisp I've hit on many areas
where it doesn't "work right". After a little reading, testing and playing I
always find that it was me that wasn't "working right". IOW, I needed to
think slightly differently (one of the reasons I find lisp highly
addictive).

So, I'm looking at this situation and I'm trying to understand where I'm not
"working right". The idea behind what I want to do is (appears?) simple, I
want to scan a directory for directories and descend into them and deal with
the contents. The fact that this isn't as trivial as most operations are in
lisp means that I'm now questioning the design.

So, I'm interested in how others might approach this. Am I thinking about
the problem in "non-lisp" terms and is there a "lisp-like" method sat there
waiting for me to notice?

Thoughts and pointers would be appreciated.

-- 
Take a look in Hagbard's World: |      5x5.el - Silly little puzzle.
http://www.acemake.com/hagbard/ | binclock.el - emacs binary clock.
http://www.hagbard.demon.co.uk/ |  uptimes.el - Record emacs uptimes.
emacs software, including.......| handyurl.el - Recall lists of URLs.
From: Kent M Pitman
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <sfwg132rwcm.fsf@world.std.com>
··········@hagbard.demon.co.uk (Dave Pearson) writes:

> So, I'm looking at this situation and I'm trying to understand where
> I'm not "working right". The idea behind what I want to do is
> (appears?) simple, I want to scan a directory for directories and
> descend into them and deal with the contents. The fact that this
> isn't as trivial as most operations are in lisp means that I'm now
> questioning the design.
> 
> So, I'm interested in how others might approach this. Am I thinking
> about the problem in "non-lisp" terms and is there a "lisp-like"
> method sat there waiting for me to notice?

In this particular situation, for example, the issue is that the pathname
model is designed around many more operating systems and file systems than
you can probably imagine, and they varied in lots of ways.  In some of
those files systems, directories were files and in others they were not.
The language, as a rule, can't solve problems that are intrinsic to the
real world and the constraint that CL would have to deal with systems
that did and didn't have this capability was real.  Probably we should have
done like we did with bit-decoding floats (where you can ask all kinds
of obscure questions about the reprsentation of your floats) and allow you
to ask questions like "are directories files here?"  The problem is that
the source material for the language was largely the Lisp Machine in this
area and it already had a hugely more articulated model than you see in 
CL.  The design committee was reluctant to adopt it since to them, at
the time, the pathname model seemed like overkill and they wanted to really
only adopt about half of what the lispm alrady proved was needed to
really do things right.  Whether you are "thinking unlispily" or whether
we, the language designers, fell down on the job is a matter of perspective.
In this particular case, I'd say the latter.  Maybe what you're noticing
is that statistically some of the time, we goofed up, and so if you either
rely on a model that says that we are infallible or that you are infallible,
you are probably in error.  A hybrid model seems most appropriate.

If you offer a few more examples, it would be possible to confirm whether
this is an adequate summary of the phenomena you're up against.  I don't
have the time to search Deja News myself to consolidate the data that
is probably already there, but if you do the consolidation, I'm sure I and
others will be happy to opine.
From: Lyman S. Taylor
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <3781EEC0.2C19AABC@mindspring.com>
Kent M Pitman wrote:

> ....          In some of
> those files systems, directories were files and in others they were not.

   But there were probably always "directories".  They're still meaningful
   objects of the file system.  There must be some persistant physical manifestation 
   of them on the "disk".  Perhaps not as legal targets for stream operations, but there
   are files that aren't legal targets for stream  operations (e.g., where there is concept
   of ownership and rights). 
  
> of obscure questions about the reprsentation of your floats) and allow you
> to ask questions like "are directories files here?" 

   The "multiple personality disorder" to me is that there is an ENSURE-DIRECTORIES-EXIST.
   So you can create it, if necessary, but you can't definatively query to see if 
   it is there in first place.  The latter being a subset process of the former. 

   So in a way, you can ask that question.  It just requires an unintentioned side 
   effect. 

---

Lyman
From: Kent M Pitman
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <sfw4sjiufmc.fsf@world.std.com>
"Lyman S. Taylor" <············@mindspring.com> writes:

>    The "multiple personality disorder" to me is that there is an
>    ENSURE-DIRECTORIES-EXIST.  So you can create it, if necessary,
>    but you can't definatively query to see if it is there in first
>    place.  The latter being a subset process of the former.

Historically this is because of outright desperation, as a patch on the
pre-designed system, and because this function is carefully designed not
to have to name a directory as an object, but rather to name a file
that is in the directory in order to side-step the issue of what directory
might return.

>    So in a way, you can ask that question.  It just requires an
>    unintentioned side effect.

If you're looking for how to understand one is present and not the
other, from a historical point of view, the right way to say, it
though, is as I said above: "You can create the directory without
having to check for it first."

fs:directory-list on the Lisp Machine had all the relevant
functionality from long before, but getting it into the language was
politically complicated for some reason.  Sometimes I think maybe
people had too literal a reading of how tightly related DIRECTORY had
to be with what the native file system returned.  Perhaps the idea
they had was that you couldn't make a pretend file to go in the
DIRECTORY listing.  Could also have been that they thought the process
of inquiring about such a thing on some file system was too expensive.
From: Kent M Pitman
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <sfw4sjh4qjg.fsf@world.std.com>
··········@hagbard.demon.co.uk (Dave Pearson) writes:

> > If you offer a few more examples, it would be possible to confirm whether
> > this is an adequate summary of the phenomena you're up against.
> 
> Examples? Do you mean examples of problems with getting a list of
> directories or do you mean examples of problems with lisp in general? If the
> former, I've only got the one I wrote about. If you mean the latter then
> I've got no examples to offer at the moment, besides, I wouldn't want to rob
> myself of the fun of attempting to solve them first.

Oh, ok.  I was asking the latter and thought you'd had several go-arounds
already and were trying to get to a meta-understanding that unified them.
From: Lyman S. Taylor
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <3781E657.11A7C0E0@mindspring.com>
Dave Pearson wrote:
..
> So, I'm interested in how others might approach this. Am I thinking about
> the problem in "non-lisp" terms and is there a "lisp-like" method sat there
> waiting for me to notice?

   In this case I think you looking for the "Holy Grail".  You want a portable solution
   to a implementation dependent problem.  I'd work at finding the small enough abstraction
   to get done what you need.  You can layer the rest of your code upon that abstraction
   and only have to worry about porting that small substrate from implementation
   to implementation.  It is annoying, but it happens from time to time.

   I don't think it is a "lisp-like"/"non-lisp" problem.  Language standards can't cover
   "everything". This is one of cases where either a more rigid universal model should  
   have been prescribed or just skip the issue.  Halfway measures can cause just as many
   problems as either extreme. 

   In reading through the HyperSpec there's no "solid" definition of file/directory.  There
   is a defintion, but you could pilot a supertanker through it. So the
   function DIRECTORY is seemingly just a portable "name", I don't see how it could ever 
   be portable in a meaningful semantic way under those conditions. 

   Sorry about the not-so-portable code.  I sort of quickly hacked that out inbetween 
   compiles of some other code I was working on.  Didn't have the thinking cap all the 
   way on. :-( 

----

Lyman
From: Christopher R. Barry
Subject: Re: Getting at directories with DIRECTORY
Date: 
Message-ID: <87emilem1g.fsf@2xtreme.net>
··········@hagbard.demon.co.uk (Dave Pearson) writes:

> As it is, when this app gets running it'll be running with clisp so
> I'll probably do something specific to the implementation. I notice
> that both clisp and ACL provide some access to the likes of
> opendir/readdir/closedir.

Yes, every Lisp has file-system operations extensions. You really only
need 1 to 3 tops non-standard functions to do everything you're
probably going to want to do, so just stick with the CLISP API and if
you want to port it to Allegro or CMU or something else, all you'll
have to do is spend a few minutes of your time weeding through the
excellent hypertext documentation that each implementation provides to 
find their equivalent function and then write a simple macro to wrap
calls to their function to the CLISP function.

Christopher