Project

General

Profile

Feature #15363

Case insensitive file systems - add info to CONFIG or somewhere?

Added by MSP-Greg (Greg L) 8 months ago. Updated 8 months ago.

Status:
Open
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:90198]

Description

I was under the impression that Windows was the only case insensitive file system. That is not the case. In RubyGems, there are places in both code and tests where this needs to be accounted for.

Although none come to mind, the same may exist here. I haven't seen anything defining it's state. If I'm not mistaken, could something like the following be added, maybe as an additional CONFIG key or constant somewhere?

if __FILE__ != __FILE__.downcase
  FS_CASE_INSENS = File.exists?(__FILE__.downcase)
elsif __FILE__ != __FILE.upcase
  FS_CASE_INSENS = File.exists?(__FILE__.upcase)
else
  FS_CASE_INSENS = true # indeterminate? assume true?
end
p "FS_CASE_INSENS #{FS_CASE_INSENS}"

Thanks, Greg

History

Updated by Hanmac (Hans Mackowiak) 8 months ago

i don't think that works that easy because it depends on the filesystem which depends on the location of the file.

For example it might be that it's case insensitive in one location and sensitive on another.

Updated by ahorek (Pavel Rosický) 8 months ago

it looks like Ruby checks only a platform for the case-(in)sensivity

for example on WSL I can create a file in my home folder which is case-sensitive

touch aAa.txt
touch aaa.txt

this creates two separate files

if I do the same in /mnt/c/* which is a remote case-insensitive NTFS filesystem. It creates only one.

on Windows

irb(main):002:0> Dir['c:/aaa.txt']
=> ["c:/aAa.txt"]

on WSL

irb(main):002:0> Dir['/mnt/c/aaa.txt']
=> [] (wrong)

irb(main):002:0> Dir['/mnt/c/aAa.txt']
=> ['/mnt/c/aAa.txt']

note that Ruby has a significant perf impact on case-insensitive filesystem already. In order to support this feature, Ruby would have to check filesystem capabilities on the fly and on every single FS operation that matters. For that reason I don't care much about fixing it.

Updated by MSP-Greg (Greg L) 8 months ago

ahorek (Pavel Rosický) & Hans,

Thanks for the feedback. Both of you are right, there isn't a trivial solution to this.

Ok to close. The code had an error in it also...

Updated by ahorek (Pavel Rosický) 8 months ago

unlike ruby, shell's glob finds a file, but it doesn't return a real filename as a result.

ls /mnt/c/aaa.txt
=> /mnt/c/aaa.txt (wrong)

ls /mnt/c/aAa.txt
=> /mnt/c/aAa.txt

https://ruby-doc.org/core-2.5.0/Dir.html
Note that the pattern is not a regexp, it's closer to a shell glob. See File.fnmatch for the meaning of the flags parameter. Case sensitivity depends on your system (File::FNM_CASEFOLD is ignored), as does the order in which the results are returned.

Updated by nobu (Nobuyoshi Nakada) 8 months ago

Case-sensitiveness is runtime environment property, and may differ per mounted volumes.

Updated by nobu (Nobuyoshi Nakada) 8 months ago

Now I can't remember why File::FNM_SYSCASE is 0 on macOS..., maybe it can select case-sensitive filesystems.

Updated by MSP-Greg (Greg L) 8 months ago

Now, I'm pretty much only windows, but previously the network I used had Windows, MacOS/OSX, and a few of *nix NAS devices. I vaguely recall some casing issues. Unfortunately, I can't test anything like that now.

Maybe the questions are:

  1. Should Ruby attempt to account for case insensitive file systems? The main issue I've come across is in comparisons using ENV variables that contain paths.

  2. If #1 is yes, is that (reasonably) possible?

Updated by nobu (Nobuyoshi Nakada) 8 months ago

You can't compare path names just by case-insensitiveness, on Windows.
Consider short file names.
You can compare them by File.identical? instead, or should use File.expand_path before comparison at least.

Updated by MSP-Greg (Greg L) 8 months ago

nobu (Nobuyoshi Nakada) wrote:

You can't compare path names just by case-insensitiveness, on Windows.
Consider short file names.
You can compare them by File.identical? instead, or should use File.expand_path before comparison at least.

Thank you for the mention of File.indentical?, as I have never noticed that method. Using File.exist? does correctly identify Windows as being case sensitive, but will give a false positive if, for instance, one has folders /Ruby and /ruby on a case sensitive file system. Unlikely, but possible...

I'm not sure about the effect of short file names. If test is a string, and File.exist? test is true, then the following should work?

fs_case_insens =
  (test != test.upcase   && File.identical?(test, test.upcase  )) ||
  (test != test.downcase && File.identical?(test, test.downcase)

Updated by nobu (Nobuyoshi Nakada) 8 months ago

MSP-Greg (Greg L) wrote:

I'm not sure about the effect of short file names. If test is a string, and File.exist? test is true, then the following should work?

fs_case_insens =
  (test != test.upcase   && File.identical?(test, test.upcase  )) ||
  (test != test.downcase && File.identical?(test, test.downcase)

As far as test contains alphabets, yes, probably.
Or maybe File.identical?(test, test.swapcase).

Also available in: Atom PDF