I would like to determine if the user's locale uses UTF-8 encoding.

This seems a little bit ugly:

[[ $LANG =~ UTF-8$ ]] && echo "Uses UTF-8 encoding.."

is there a more general/portable way?

  • 1
    What exactly you want? (why [ $LANG =~ UTF-8$ ]] && echo "Uses UTF-8 encoding.." is ugly?) – Pandya Jun 18 '15 at 16:20
  • @Pandya Will it work on all systems? What if LANG is not defined? What if LANG uses lower case letters utf-8, and so on.. – Håkon Hægland Jun 18 '15 at 16:51
  • 1
    @Pandya It fails if the encoding is defined through LC_CTYPE, LC_ALL or LANGUAGE, or if the encoding name uses a variation on the suffix such as utf8. – Gilles 'SO- stop being evil' Jun 18 '15 at 21:39

From Wikipedia :

On POSIX platforms, locale identifiers are defined similarly to the BCP 47 definition of language tags, but the locale variant modifier is defined differently, and the character encoding is included as a part of the identifier.

It is defined in this format: [language[_territory][.codeset][@modifier]]. (For example, Australian English using the UTF-8 encoding is en_AU.UTF-8.)

However, if the codeset suffix is missing in the locale identifier, for example as in en_AG (see this question), then the codeset is defined by a default setting for that locale, which could very well be UTF-8. As a result, the current encoding cannot be determined by looking at the LANG environment variable.

Further, the locale command only shows the current values of the environment variables.. so it seems that that command cannot be used to determine the codeset either..

However, there is a Perl module I18N::Langinfo, see also this question that seems to be a solution:

perl -MI18N::Langinfo=langinfo,CODESET -E 'say "Uses UTF-8 encoding .." if langinfo(CODESET()) eq "UTF-8"'

This Perl module is a wrapper for the C library function nl_langinfo.

  • 2
    For people wanting to avoid calling Perl, the manpage of nl_langinfo(3) on CODESET notes "This is the same string that you get with locale charmap." – mleu Jul 23 '18 at 16:06

On POSIX system, you can use locale:

$ if (locale | grep -e 'utf8' -e 'UTF-8') >/dev/null 2>&1; then echo UTF8; fi

There is charmap attribute in the LC_CTYPE locale category that can be used for this:

locale charmap | grep -qi 'utf-\+8' && echo "Uses UTF-8 encoding.."

It is a bit more robust that parse the locale name.

(answer updated base on the Bluehorn for suggestion, thanks!)

  • 1
    Just learned: The easiest way is calling locale charmap which will just return the character set of the current locale. – Bluehorn Jun 21 '19 at 13:46

To take care of the cases in which the locale string contains a lowercase utf8 substring, you can set bash's nocasematch option and make the dash optional:

shopt -s nocasematch
[[ $LANG =~ UTF-?8$ ]] && echo "Uses UTF-8 encoding.."

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.