15

I just read the following sentence:

Case Sensitivity is a function of the Linux filesystem NOT the Linux operating system.

What I deduced from this sentence is if I'm on a Linux machine but I am working with a device formatted using the Windows File System, then case sensitivity will NOT be a thing.

I tried the following to verify this:

$ ~/Documents: mkdir Test temp

$ ~/Documents: touch Test/a.txt temp/b.txt

$ ~/Documents: ls te*
b.txt

And it listed only the files within the temp directory, which was expected because I am inside a Linux Filesystem.

When I navigated to a Windows File System (NOTE: I am using WSL2), I still get the same results, but I was expecting it to list files inside both directories ignoring case sensitivity.

$ /mnt/d: mkdir Test temp

$ /mnt/d: touch Test/a.txt temp/b.txt

$ /mnt/d: ls te*
b.txt

I tried it with both bash and zsh.

I feel that it's somehow related to bash (or zsh), because I also read that bash enforces case sensitivity even when working with case insensitive filesystems.

This test works on Powershell, so it means that the filesystem is indeed case insensitive.

4
  • 1
    What does "case-sensitive" mean in many non-latin languages? Jun 28 at 0:05
  • 2
    Where did you read the sentence? It does not sound like something that is true in all contexts, since many parts of the Linux kernel and of Linux-based operating systems that deal with files are indeed case sensitive.
    – James_pic
    Jun 29 at 11:16
  • 3
    @JeremyBoden That's a good, but separate, question. See unicode.org/reports/tr21/tr21-5.html for some discussion of caseless matching across various languages. ("Case sensitive" is pretty straightforward; "case insensitive" is the complicated one.)
    – LarsH
    Jun 29 at 14:11
  • 3
    Keep in mind that NTFS is actually case-sensitive, and it's just a Windows compatibility layer that makes it not so. If your Windows file system is using NTFS, odds are it's actually case sensitive as well Jun 29 at 22:20
32

Here, you're running:

ls te*

Using a feature of your shell called globbing or filename generation (pathname expansion in POSIX), not of the Linux system nor of any filesystem used on Linux.

te* is expanded by the shell to the list of files that match that pattern.

To do that, the shell requests the list of entries in the current directory from the system (typically using the readdir() function of the C library, which underneath will use a system-specific system call (getdents() on Linux)), and then match each name against the pattern.

And unless you've configured your shell to do that matching case insensitively (see nocaseglob options in zsh or bash) or use glob operators to toggle case insensitivity (like the (#i) extended glob operator in zsh), te* will only expand to the list of files whose name as reported by readdir() starts with te, even if pathname resolution on the system or file system underneath is case insensitive or can be made to be like NTFS.

7
  • 1
    So, basically you mean to say that I am not testing the statement correctly, could you please tell how can I validate the authenticity of that statement? Jun 27 at 19:01
  • 19
    Create a file called "TEST". Then try to create one called "test". You can do this on native linux filesystems, have two files with different case only. But not on Windows filesystem. Similarly, create "TEST" and then do "cat test" to see the contents - works on Windows,
    – pjc50
    Jun 27 at 21:38
  • 9
    @pjc50 this is unambigously correct for VFAT, but not for NTFS, where at least ntfs-3g uses POSIX namespace by default, thus allowing filenames in a single directory to differ only by case.
    – Ruslan
    Jun 28 at 11:23
  • @pjc50 On FAT, the name with a dot still refers to the same file. For example TEST..
    – 7h3yskr8
    Jun 29 at 3:27
  • 2
    @LarsH basically, yes. But note that NTFS is not intrinsically case sensitive: Windows namespace is case insensitive, and ntfs-3g can follow this with mount options like ignore_case,windows_names.
    – Ruslan
    Jun 29 at 14:29
18

As Vojtech explained, NTFS is case sensitive. Trying it on a FAT file system will work, but only if you use a case-folding variant, i.e. msdos on Linux (I don’t know if there’s an equivalent on WSL). With this variant of FAT, file names are all lower-cased, so Test shows up as test.

There are a number of aspects to consider regarding case sensitivity in file systems:

  • whether the file system itself stores case information;
  • whether the expected use of the file system considers case;
  • whether the file system driver or the operating system maps case, i.e. whether a file can be found ignoring case;
  • how to map case.

Historical FAT, as implemented in the msdos, is somewhere in between the first two: technically, FAT can store case, but in practice it wasn’t used that way, and MS-DOS and its clones folded case (so readme.txt and README.TXT and ReAdMe.TxT are all valid ways to access README.TXT). Windows preserves this behaviour, even on case-preserving file systems (including VFAT and NTFS). The msdos file system driver handles this by mapping all file names to lowercase, which isn’t quite right but produces consistent results and avoids problems with Unix-style tools’ and users’ expectations. So on Linux, mounting a file system using the msdos driver means that README.TXT can only be accessed through readme.txt, not through any of the variants including those shown above.

Your quote stems from the fact that the Linux kernel itself doesn’t particularly care, at least on the surface: one could imagine a file system where open("README.TXT") and open("ReAdMe.TxT") would open the same file. Indeed XFS can be configured in this way, at least for ASCII file names (it is then case preserving, but provides case-insensitive lookups). However things quickly get more complicated for general-purpose scenarios, and there has been much discussion over the years; see for example Filesystems and case insensitivity, Case-insensitive filesystem lookups, and Case-insensitive ext4 on LWN.

4
  • I am just a beginner in all this stuff so it will take some time to wrap my head around this. But meanwhile could you please tell that is it anyhow related to BASH? I've added few points in my question if you could check that. Jun 27 at 11:27
  • See also the lowntfs-3g fuse driver to get a similar behaviour as that of that msdos driver you're mentioning. Jun 27 at 19:19
  • 1
    It is not related to the shell you are using. NTFS is case-sensitive, the normal WIn32 API's are not. Jun 27 at 21:11
  • 1
    @SomShekharMukherjee a typical Linux-based operating system is not a monolith, but composed of a number of components created by a number of unrelated projects. Most Linux file systems are case sensitive, so many projects assume file names are case sensitive, and may behave surprisingly if the underlying file system is case insensitive. BASH is at least somewhat aware of this, and has options to help with this, but its defaults are still to assume case sensitivity, like most Linux applications would.
    – James_pic
    Jun 29 at 11:26
10

That's because NTFS is also case sensitive, but Windows hides it from users. FAT is case insensitive, you can check by trying to create test and Test directories in the same directory:

$ ls
test
$ mkdir Test
mkdir: cannot create directory ‘Test’: File exists
$ mkdir TEST
mkdir: cannot create directory ‘TEST’: File exists

It's actually more a little bit more complicated than this and your ls test won't work even with FAT because it actually is case preserving -- it won't allow you to create Test and test directories but it still makes difference between those two cases (and between T* and t*) so ls t* for test and Temp won't list content of both.

5
  • That's really confusing for me, so does the statement actually mean anything and is there a way to test it? Jun 27 at 11:15
  • I feel that it's somewhere related to Bash (or ZSH), because I also read that Bash enforces case sensitivity even when working with case insensitive file systems. And this test works on Powershell so it means that the file system is indeed case insensitive. Jun 27 at 11:18
  • I think the mkdir I showed tests the statement: you can't create Test and test in same directory on (V)FAT filesystem, but you can do it on NTFS or Ext4 and XFS and other linux native filesystems. That should be enough to show that case sensitivity is based on filesystem and not operating system. The case preservation makes it a little bit confusing and I didn't realize this when answering initially but I think Stephen's answer made this clearer. Jun 27 at 11:28
  • So you mean it doesn't matter what shell I am using I will always get the same results in this case? In short shell doesn't play any role here, right? Jun 27 at 11:30
  • In theory the shell could "play a role" in this if it was programmed to do that, but that's not the case with "normal" linux shells. Jun 27 at 11:45
2

I question the quote text; An operating system is case-agnostic--it is not usually case sensitive or insensitive. Instead, the command line shells and/or file system drivers are what make case matter or not.

And even then is is not that simple: Computers are numerical machines, not textual. The signals and data all have numerical values associated. Text usually uses the 7-bit ASCII code (in 8-bit groups, so the 8th bit is always 0 in ASCII. Unicode, ANSI, etc, complicate this even more.), where upper and lower case codes are different. Here are the codes for 'A' and 'a' (in binary):

A  01000001
a  01100001

At various levels (kernel, shell, files system driver, CPU, and others), the numerical values are case agnostic since there is no such thing as an upper-/lower-case 1 and 0.

Also be aware of the concept of "globbing". Globbing is the idea of using '*' or '?' to "match" anything--even nothing--in different scenarios and rules, depending one which glob character was used.

In a typical Unix-like shell, such as Bash, the shell will do the globbing: in ls *, the shell will expand the '*' with a list of matched filenames, before starting the ls command and pass it the list of matched names, not the '*'.

A typical "msdos" style shell will not do this. In this situation, the cmd.exe shell would start the ls.exe command (assuming it exists!) and pass it a single '*'. It is then up to the ls.exe command to handle the expansion of '*' according to it's own rules.

Add in the file systems... EXT (Unix) file systems are case sensitive. FAT file systems are case insensitive (look at an old FAT floppy image--the filenames are stored using UPPERCASE ASCII), which is complicated more with FAT32 and LFN (long file name support). And NTFS, which tries to bridge the gap by being both--NTFS is generally case-preserving while ignoring case when it tries to match a filename (remember as well, the filename is stored as a sequence of numerical data).

In the example given, ls te*, the bash shell gives you additional options. For example, try ls [Tt]e*, and it will match both 'Test' and 'temp', but not 'TECH'.

As you can see, the situation is very complex. And the exact question asked about the statement given is also a complex situation, further complicated because the statement is questionable without additional qualifications and context.

1
  • 3
    NTFS is really funny with cases - it stores the rules on the disk itself! It's modern enough that Microsoft was aware of the fact that there's no single global rule how case sensitivity works, but you need a rule in order to exchange disks between systems.
    – MSalters
    Jun 28 at 0:06
1

There is a point that is worth calling out specifically, that potentially puts some of these answers into context.

On Linux, all system calls that deal with filenames deal with strings of bytes. That is to say, that whenever a program asks to do something with the file system, it will specify any filenames it is working with as a string of bytes, and any filenames that are returned to it will be strings of bytes. Often (although this is not enforced), these strings will contain ASCII or UTF-8 encoded text, and the binary representations of upper and lower case letters in these encodings are different. So anything that treats filenames as "just binary data" is case sensitive.

Once these requests get to the filesystem driver, some filesystems will interpret file names case sensitively (typically ones created for Linux or other Unix operating systems) and some will interpret file names case insensitively (typically ones created for other operating systems, such as Windows). But these are internal implementation details that programs cannot see - all they see are strings of bytes.

Typically, programs will not attempt to determine whether the filesystem they are running on is case sensitive or not, and many programs will implicitly assume that filesystems are case sensitive (since this is the simplest to implement). Some may have configuration options to allow them to work with case, but remember that all the filesystem will ever talk to them about is strings of bytes, so this isn't something that programs can work out from the filenames they see.

0

I think the quote is not only, as this answer correctly points out, ambiguous and context-dependent, but altogether misleading, because of the use of "sensitive" and "function". Actually, both the Linux kernel and Linux or GNU/Linux or Unixoid operating systems, as well as native Linux file systems, are "case-sensitive" exactly because they have absolutely no concept of "case". For Linux, the difference between a and A is just the same as that between a and b: two different code points, one (or more) bits switched (and neither below decimal 32 nor above decimal 127, to leave special cases aside). Any idea of a somewhat particular relation between lower- and uppercase "A" that is something else than that between two code points is either imposed by other contexts (like C code) or pure convention (adherence to which may still be expected by tools, though!).

The confusion is unavoidable because not having a concept of something completely contradicts our notion of being sensitive about the same thing. If a spell checker claims to be grammar-sensitive, we expect it to recognize rules beyond pure spelling, or, in order to be less metaphorical, its programmers to have implemented functions that in some way or other deal with the concept of grammar. And while the Linux programmers (in any of the meanings mentioned above) certainly all have a concept of character case, they just did not implement any of that in the system.

Also, not having a concept about something is usually not regarded a function. However, mapping a to A, thereby either not allowing test.txt besides TEST.TXT or, worse, making the two indiscernable, is a function that has to be explicitly implemented in the OS or the file system or whatever layer we're talking about in a specific context. And this function disguises as the absence of a function by calling it "case-insensitivity". What it provides is an interface that allows for the user being insensitive about holding or not holding the shift key when typing a filename. (And the only possible explanation of why someone once thought this to be advantageous is the common misconception that less expressive user interfaces are easier to understand - but that is beyond the scope of the question.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.