Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save anandkkpr/333a83797290b838fa5430c742311170 to your computer and use it in GitHub Desktop.
Save anandkkpr/333a83797290b838fa5430c742311170 to your computer and use it in GitHub Desktop.

What's this about?

I am a lifetime Windows user and (like many people) I am used to organising important files on Windows machines by starting the file name with _ (underscore).

I found a hack that allows users to enable update a locale language def file in Debian (Ubuntu Mint) here. This didn't work fully on Fedora so, after some help from the folks on Fedora Forum, I was able to figure out how to implement a system-update resilient (most of the time) way to enable "sort underscore in file system first" sorting (aka collating). Here's the thread on Fedora Forum.

Some Notes

First and most important: locale-gen does not exist on fedora. The file mentioned by @markos was a "bash completion" file - not sure what it is doing on Fedora because locale-gen is not a thing on RHEL systems.

Second (and this is what took time to figure out): the thing that locale-gen does is actually handled by the cross-Nix tool, localedef.

SO!, to make this a repeatable process (and as a future ref to myself)... I've put this Gist together based on the Fedora Forum thread.

Instructions

  1. Install the missing locale definition files by running: dnf install glibc-locale-source
  2. Edit the various locale definition files by creating copies of the originals (in my case, I use en_GB which is what I was working with) - as described in the Linux Mint forum post:
## STEP {1}
cd /usr/share/i18n/locales
sudo cp en_US en_US_edited
sudo cp iso14651_t1 iso14651_t1_edited
sudo cp iso14651_t1_common iso14651_t1_common_edited

## STEP {2}
sudo vim en_US_edited
# locate and change the following line in the file
#   copy "iso14651_t1"
# to
#   copy "iso14651_t1_edited"

## STEP {3}
sudo vim iso14651_t1_edited
# locate and change the following line in the file
#   cp "iso14651_t1_common"
# to
#   copy "iso14651_t1_common_edited"

## STEP {4}
sudo vim iso14651_t1_common_edited
# locate and change the following line in the file
#   <U005F> IGNORE;IGNORE;IGNORE;<U005F> % LOW LINE
# to
#   <U005F> <RES-1>;IGNORE;IGNORE;<U005F> % LOW LINE

AND HERES WHERE FEDORA DIGRESSES

Because Fedora doesn't have a /var/lib/supported.d/en file NOR the locale-gen helper script/command, we need to directly use localedef which IS available across all modern *Nix distros (as far as I can tell) to do the locale compilation. Here are those missing steps:

# STEP {5}
# Tell localedef to create the new dir structure the system expects/needs FIRST:
localedef --no-archive -f UTF-8 -i en_US_edited /usr/lib/locale/en_US_edited.utf8

# STEP {6}
# Get localedef to compile the new/hacked locale. NOTE: I'm not sure if this is mandatory
# but the last argument, the full file path, is likely not needed BUT, I used the full path AND
# I also used the file convention for UTF-8 locales that I saw there already. Thus, the end of the
# "outputpath" argument to localedef (see `man localedef` for parameter/option info) is:
# en_US_edited.utf8 AND NOT en_US_edited.UTF-8
# Again, I'm not sure if this was required or not.
localedef -f UTF-8 -i en_US_edited /usr/lib/locale/en_US_edited.utf8

# STEP {7}
# This step MAY ALSO NOT BE NEEDED - but I ran it just to be sure because after some reboots,
# localectl (more on that in the next steps) didn't seem to be setting the new modified locale.
localedef --add-to-archive -f UTF-8 -i en_US_edited /usr/lib/locale/en_US_edited.utf8

# STEP {8}
# Next, check to see that your edited/modified locale can be detected by the system.
localectl list-locales | grep en_US_edited

# You should see the following (note that it ends in UTF-8 and not lower case utf8 - again,
# I'm not sure what, if any, significance this has):
#   > en_US_edited.UTF-8

# If you see your modified locale, you should be good to continue.

# STEP {9}
# Set your default machine locale.
localectl set-locale en_US_edited.UTF-8

# STEP {10}
# You will need to LOGOUT and LOGIN - a reboot SHOULD NOT be necessary because
# locale is set on a per-login session basis.

# STEP {11}
# As your regular user, you should be able to simply run `locale` and see that the system
# is using the newly hacked/modified locale:
locale

# Desired ouput:
#   > LANG=en_US_edited.UTF-8
#   > LC_CTYPE="en_US_edited.UTF-8"
#   > LC_NUMERIC=en_CA.UTF-8
#   > LC_TIME=en_CA.UTF-8
#   > LC_COLLATE=en_US_edited.UTF-8
#   > ...(SNIP)

IMPORTANT CLOSING NOTE

I've been struggling with this annoying system setting for a LONG LONG TIME. As such, I actually rebooted a few times before realising that my Fish Shell user config file was overriding default locale for LC_COLLATE. (Facepalm). As suggested in MANY forums that talk about re-sorting file system sorting so that "underscore" ("_") IS NOT ignored, I had set LC_COLLATE to be LC_COLLATE=C. This had the effect of negating all the work described hereabove.

IF you have been struggling to get underscores to matter, you MIGHT have set LC_COLLATE to "C" also... check your .bashrc, .zshrc and/or config.fish file! The moment I commented out this line in my ~/.config/fish/config.fish file, the system started to work the way I've been so desperate to have it work!

Addendum: Some links that helped me figure things out:

  1. localedef manual page: https://www.man7.org/linux/man-pages...caledef.1.html
  2. locale manual page: https://www.man7.org/linux/man-pages/man1/locale.1.html -> NOTE: Locale actually has the following code snippet at the bottom of its man page:
       The following example compiles a custom locale from the ./wrk
       directory with the localedef(1) utility under the $HOME/.locale
       directory, then tests the result with the date(1) command, and
       then sets the environment variables LOCPATH and LANG in the shell
       profile file so that the custom locale will be used in the
       subsequent user sessions:

       $ mkdir -p $HOME/.locale
       $ I18NPATH=./wrk/ localedef -f UTF-8 -i fi_SE $HOME/.locale/fi_SE.UTF-8
       $ LOCPATH=$HOME/.locale LC_ALL=fi_SE.UTF-8 date
       $ echo "export LOCPATH=\$HOME/.locale" >> $HOME/.bashrc
       $ echo "export LANG=fi_SE.UTF-8" >> $HOME/.bashrc

The code above allows you to essentially create a custom user home folder that contains custom locales. You STILL need to ensure you have glibc-locale-source installed so that you have the base locale definition files to work off of.

Again... The Linux Mint forum post that showed me that this sort of operation was even possible. The forum post works perfectly on Debian based systems. I hope that this Gist here ultimately proves useful to other RHEL / Red Hat / Fedora / Rocky Linux / AlmaLinux users who are used to using the _ (underscore) as a critical part of their day-to-day file organisation habits.

Cheers!

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