Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File::Glob::NO_CASE doesn't have effect without metacharacters #13701

Open
p5pRT opened this issue Apr 2, 2014 · 7 comments
Open

File::Glob::NO_CASE doesn't have effect without metacharacters #13701

p5pRT opened this issue Apr 2, 2014 · 7 comments

Comments

@p5pRT
Copy link

p5pRT commented Apr 2, 2014

Migrated from rt.perl.org#121566 (status was 'open')

Searchable as RT121566$

@p5pRT
Copy link
Author

p5pRT commented Apr 2, 2014

From @Smylers

This is a bug report for perl from Smylers@​stripey.com,
generated with the help of perlbug 1.40 running under perl 5.19.11.


File​::Glob has a GLOB_NOCASE option, documented as making bsd_glob treat
case differences as not significant. However GLOB_NOCASE doesn't have
any affect if the glob pattern doesn't have any metacharacters.

This can be seen on a case-sensitive file system by creating two files
which just differ in case. Handily, the perl source directory after
building has both makefile and Makefile (at least on Linux). Searching
for "makefile" only returns the filename which matches that case​:

  $ ./perl -Ilib -MFile​::Glob=bsd_glob,GLOB_NOCASE -E 'say foreach bsd_glob "makefile", GLOB_NOCASE'
  makefile

But introducing some otherwise-pointless metacharacters by using the
pattern "makefil[e]" makes the match case-insensitive​:

  $ ./perl -Ilib -MFile​::Glob=bsd_glob,GLOB_NOCASE -E 'say foreach bsd_glob "makefil[e]", GLOB_NOCASE'
  Makefile
  makefile

Note that [e] only matches a single letter "e", so those two patterns
should yield identical results.

Passing glob a constant string without any metacharacters in it may
generally seem like a useless use of glob (you apparently know the
filename already, and could just perform an -e test on it), but with
GLOB_NOCASE it is a useful thing to do​: it lets you check for a file
with the specified name existing in any case.



Flags​:
  category=library
  severity=low
  module=File​::Glob


Site configuration information for perl 5.19.11​:

Configured by smylers at Wed Apr 2 15​:57​:20 BST 2014.

Summary of my perl5 (revision 5 version 19 subversion 11) configuration​:
  Commit id​: a04e6aa
  Platform​:
  osname=linux, osvers=3.11.0-19-generic, archname=x86_64-linux
  uname='linux fozzie 3.11.0-19-generic #33-ubuntu smp tue mar 11 18​:48​:34 utc 2014 x86_64 x86_64 x86_64 gnulinux '
  config_args='-des -Dusedevel'
  hint=previous, useposix=true, d_sigaction=define
  useithreads=undef, usemultiplicity=undef
  use64bitint=define, use64bitall=define, uselongdouble=undef
  usemymalloc=n, bincompat5005=undef
  Compiler​:
  cc='cc', ccflags ='-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
  optimize='-O2',
  cppflags='-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'
  ccversion='', gccversion='4.8.1', gccosandvers=''
  intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
  d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
  ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
  alignbytes=8, prototype=define
  Linker and Libraries​:
  ld='cc', ldflags =' -fstack-protector -L/usr/local/lib'
  libpth=/usr/local/lib /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed /usr/include/x86_64-linux-gnu /usr/lib /lib/x86_64-linux-gnu /lib/../lib /usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib /usr/local/lib /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed /usr/include/x86_64-linux-gnu /usr/lib /usr/local/lib /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed /usr/include/x86_64-linux-gnu /usr/lib
  libs=-lnsl -ldl -lm -lcrypt -lutil -lc
  perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
  libc=libc-2.17.so, so=so, useshrplib=false, libperl=libperl.a
  gnulibc_version='2.17'
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
  cccdlflags='-fPIC', lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector'


@​INC for perl 5.19.11​:
  lib
  /usr/local/lib/perl5/site_perl/5.19.11/x86_64-linux
  /usr/local/lib/perl5/site_perl/5.19.11
  /usr/local/lib/perl5/5.19.11/x86_64-linux
  /usr/local/lib/perl5/5.19.11
  .


Environment for perl 5.19.11​:
  HOME=/home/smylers
  LANG=en_GB.utf8
  LANGUAGE=en_GB​:en
  LC_COLLATE=C
  LD_LIBRARY_PATH (unset)
  LOGDIR (unset)
  PATH=/home/smylers/bin​:/usr/local/sbin​:/usr/local/bin​:/sbin​:/bin​:/usr/sbin​:/usr/bin​:/usr/X11R6/bin​:/usr/games
  PERL_BADLANG (unset)
  PERL_CPANM_OPT=--sudo --prompt
  SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Apr 2, 2014

From @ikegami

On Wed, Apr 2, 2014 at 11​:29 AM, Smylers <perlbug-followup@​perl.org> wrote​:

# New Ticket Created by Smylers
# Please include the string​: [perl #121566]
# in the subject line of all future correspondence about this issue.
# <URL​: https://rt-archive.perl.org/perl5/Ticket/Display.html?id=121566 >

This is a bug report for perl from Smylers@​stripey.com,
generated with the help of perlbug 1.40 running under perl 5.19.11.

-----------------------------------------------------------------

File​::Glob has a GLOB_NOCASE option, documented as making bsd_glob treat
case differences as not significant.

Treats **file names** as case insensitive.

However GLOB_NOCASE doesn't have

any affect if the glob pattern doesn't have any metacharacters.

Comparisons are only made against file names when "[]", "?" and "*" are
used, so I suppose that's true.

But introducing some otherwise-pointless metacharacters by using the

pattern "makefil[e]" makes the match case-insensitive​:

1. It's not that the match was case-sensitive before the addition of the
metacharacters; it's that there was no match before.
2. Only "[]", "?" and "*" will induce a file check. "\" and "{}" will not.

All of this is consistent with shell globing. It looks like you're trying
to normalize Windows file names, for which there's Win32​::GetLongPathName().

@p5pRT
Copy link
Author

p5pRT commented Apr 2, 2014

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Apr 2, 2014

From @Smylers

Eric Brine writes​:

On Wed, Apr 2, 2014 at 11​:29 AM, Smylers <perlbug-followup@​perl.org> wrote​:

File​::Glob has a GLOB_NOCASE option, documented as making bsd_glob
treat case differences as not significant.

Treats **file names** as case insensitive.

Sorry, I don't follow. When comparing a filename with a pattern, surely
it's the _comparison_ that's actually case-insensitive (or not)? I don't
understand the distinction in it being specifically the filename that's
marked as being case-insensitive.

However GLOB_NOCASE doesn't have
any affect if the glob pattern doesn't have any metacharacters.

Comparisons are only made against file names when "[]", "?" and "*"
are used,

Where does the File​::Glob docs say that?

so I suppose that's true.

Even without any metacharacters, it appears only to be returning files
that actually exist. Compare this​:

  $ ./perl -Ilib -MFile​::Glob=bsd_glob,GLOB_NOCASE -E 'say foreach bsd_glob "makefile", GLOB_NOCASE'
  makefile

With this, which yields no output​:

  $ ./perl -Ilib -MFile​::Glob=bsd_glob,GLOB_NOCASE -E 'say foreach bsd_glob "no_such_file", GLOB_NOCASE'

It looks to me like the pattern is being compared against actual
filenames that exist, just that the comparison is case-sensitive,
despite GLOB_NOCASE.

All of this is consistent with shell globing. It looks like you're
trying to normalize Windows file names,

Close. What I've actually got is a Linux server using Samba to share a
(case-sensitive) ext4 directory with (case-preserving) Windows clients.
On the server I want to know if a file with a particular name has been
created in that directory. Since Windows doesn't care about the
capitalization used, and the capitalization won't make any difference to
Windows users, I don't want the server to be relying on any particular
capitalization having being used.

Hence my desire to find a file with a particular name and any
capitalization.

for which there's Win32​::GetLongPathName().

Thank you for the suggestion. But it looks like that module is only
available on Windows, so I don't think it will be of use for my
particular situation.

bsd_glob with NO_CASE is however giving exactly the result I want, so
long as I wrap square brackets around an arbitrary letter of the
filename. But it'd be less cryptic not to have to do this.

Smylers
--
http​://twitter.com/Smylers2

@p5pRT
Copy link
Author

p5pRT commented Apr 4, 2014

From @ikegami

On Wed, Apr 2, 2014 at 4​:47 PM, Smylers <Smylers@​stripey.com> wrote​:

Eric Brine writes​:

On Wed, Apr 2, 2014 at 11​:29 AM, Smylers <perlbug-followup@​perl.org>
wrote​:

File​::Glob has a GLOB_NOCASE option, documented as making bsd_glob
treat case differences as not significant.

Treats **file names** as case insensitive.

Sorry, I don't follow. When comparing a filename with a pattern, surely
it's the _comparison_ that's actually case-insensitive (or not)? I don't
understand the distinction in it being specifically the filename that's
marked as being case-insensitive.

Glob is a string generator. Not all patterns results in comparisons.

Even without any metacharacters, it appears only to be returning files
that actually exist. Compare this​:

$ ./perl -Ilib -MFile​::Glob=bsd_glob,GLOB_NOCASE -E 'say foreach
bsd_glob "makefile", GLOB_NOCASE'
makefile

With this, which yields no output​:

$ ./perl -Ilib -MFile​::Glob=bsd_glob,GLOB_NOCASE -E 'say foreach
bsd_glob "no_such_file", GLOB_NOCASE'

What? The case GLOB_NOCASE present is very inconsistent with GLOB_NOCASE
absent.

$ perl -MFile​::Glob=bsd_glob,GLOB_NOCASE -E 'say for bsd_glob "missing",
GLOB_NOCASE'

$ perl -MFile​::Glob=bsd_glob,GLOB_NOCASE -E 'say for bsd_glob "missing"'
missing

Ok, I agree there's a bug here. Specifically, these two should return the
same result​:

$ perl -MFile​::Glob=bsd_glob,GLOB_NOCASE -E 'say for bsd_glob
"mooooooooooo", GLOB_NOCASE'

$ perl -MFile​::Glob=bsd_glob,GLOB_NOCASE -E 'say for bsd_glob
"MoooOOOooooo", GLOB_NOCASE'
MoooOOOooooo

I don't know whether they should both return "mooooooooooo" (no file system
check like without GLOB_NOCASE) or MoooOOOooooo (Make the existing file
system check case in-sensitive). I can't see any drawbacks to the latter.

@p5pRT
Copy link
Author

p5pRT commented Sep 24, 2014

From @jkeenan

On Fri Apr 04 07​:03​:47 2014, ikegami@​adaelis.com wrote​:

On Wed, Apr 2, 2014 at 4​:47 PM, Smylers <Smylers@​stripey.com> wrote​:

Eric Brine writes​:

On Wed, Apr 2, 2014 at 11​:29 AM, Smylers <perlbug-followup@​perl.org>
wrote​:

File​::Glob has a GLOB_NOCASE option, documented as making bsd_glob
treat case differences as not significant.

Treats **file names** as case insensitive.

Sorry, I don't follow. When comparing a filename with a pattern, surely
it's the _comparison_ that's actually case-insensitive (or not)? I don't
understand the distinction in it being specifically the filename that's
marked as being case-insensitive.

Glob is a string generator. Not all patterns results in comparisons.

Even without any metacharacters, it appears only to be returning files
that actually exist. Compare this​:

$ ./perl -Ilib -MFile​::Glob=bsd_glob,GLOB_NOCASE -E 'say foreach
bsd_glob "makefile", GLOB_NOCASE'
makefile

With this, which yields no output​:

$ ./perl -Ilib -MFile​::Glob=bsd_glob,GLOB_NOCASE -E 'say foreach
bsd_glob "no_such_file", GLOB_NOCASE'

What? The case GLOB_NOCASE present is very inconsistent with GLOB_NOCASE
absent.

$ perl -MFile​::Glob=bsd_glob,GLOB_NOCASE -E 'say for bsd_glob "missing",
GLOB_NOCASE'

$ perl -MFile​::Glob=bsd_glob,GLOB_NOCASE -E 'say for bsd_glob "missing"'
missing

Ok, I agree there's a bug here. Specifically, these two should return the
same result​:

$ perl -MFile​::Glob=bsd_glob,GLOB_NOCASE -E 'say for bsd_glob
"mooooooooooo", GLOB_NOCASE'

$ perl -MFile​::Glob=bsd_glob,GLOB_NOCASE -E 'say for bsd_glob
"MoooOOOooooo", GLOB_NOCASE'
MoooOOOooooo

I don't know whether they should both return "mooooooooooo" (no file system
check like without GLOB_NOCASE) or MoooOOOooooo (Make the existing file
system check case in-sensitive). I can't see any drawbacks to the latter.

Discussion in this RT petered out about 5-1/2 months ago.

Suggestions as to how to move forward are welcome.

Thank you very much.

--
James E Keenan (jkeenan@​cpan.org)

@p5pRT
Copy link
Author

p5pRT commented Sep 24, 2014

From @cpansprout

On Tue Sep 23 18​:18​:17 2014, jkeenan wrote​:

Discussion in this RT petered out about 5-1/2 months ago.

Suggestions as to how to move forward are welcome.

This is a tough one. Some of us regularly use glob for things other than file globbing. <foo{1,2,3,4}> is another way of writing map("foo$_",1..4). Whether GLOB_NOCASE should change this I suppose is the question. We do have -e for the other use case (checking for files case-insensitively), but it depends on the case-sensitivity of the file system (which I suppose is a good thing).

--

Father Chrysostomos

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants