Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Case Sensitivity Bug?



"Sean B. Palmer" wrote:
> zsh is doing something very strange on OS X:
> 
> $ zsh -c 'echo test; which head'
> test
> /opt/local/bin/head
> 
> $ zsh -c 'date; which head'
> Tue Dec 16 13:57:00 GMT 2008
> /usr/bin/head
> 
> The problem centres around the case-sensitivity of HFS+, the OS X
> filesystem. I have two head binaries, one called "head", the standard
> unix head, and one called "HEAD", part of perl's lwp library:
> 
> $ which head
> /usr/bin/head
> 
> $ which HEAD
> /opt/local/bin/HEAD
> 
> As you can see from the echo and date commands, my problem is that
> invoking echo first in the shell (or invoking nothing at all) causes
> which to work in a case insensitive manner. When date is invoked first
> instead, which works in a case sensitive manner.
> 
> Why is this so?

I think it's down to command hashing.  In the second case "date" is an
external command and zsh will fill its hash of external commands as it
searches the path to find date.  The which command then relies on this.
In this case the shell is comparing the command you searched for against
an internal string, which is case sensitive.  A corollary is likely to
be that command completion is case sensitive by default (though
completion is powerful enough for you to fix this fairly generally),
since this uses the hash, too.

In the first case, there's no hash; "which" does a blind search of the
path for <path_element>/head by trying to access the file and
/opt/local/bin/HEAD matches because the comparison is done in the file
system driver.

This is inconsistent, so regardless of what the right answer for case
sensitivity is, this isn't it.  Command hashing isn't really appropriate
if searching is done case insensitively, at least not without a flag
saying the command is stored on a case insensitive system, which the
shell doesn't know.  Hence the easiest fix (without actually looking at
the code) is likely to be to make the code fully case insensitive by
adding a string comparison in the case where which searches the path
itself.

> And how does zsh manage to implement a case sensitive
> which at all?

Your file system is case preserving as well as case insensitive, so a
file name read from the disk will have a certain format which the shell
will use when it does string comparisons.

> Neither sh and bash on OS X have a case sensitive which.
> I'm using OS X 10.4.11 (Tiger).

So they're not doing that.  There's an argument that command hashing is
unnecessary on modern systems anyway, although the way it's wired into
the completion system means this is a little different in zsh from most
shells.


A trivial way of guaranteeing that "which" is case insensitive is to
use pattern matching.  This would remain even if in future we guaranteed
that the default string match was case sensitive.

  % setopt extendedglob
  % which -m '(#i)head'
  /usr/bin/HEAD
  /usr/bin/head

(here on Fedora 8, hence file system is actually case sensitive).

-- 
Peter Stephenson <pws@xxxxxxx>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070



Messages sorted by: Reverse Date, Date, Thread, Author