読者です 読者をやめる 読者になる 読者になる

clock-up-blog

go-mi-tech

README のファイル名が大文字である理由

慣習 文字コード 雑学

README のファイル名は慣習的にすべて大文字(であることが多い)

GitHub でプロジェクトを作るときに README を作成するオプションを入れておくと、README.md というファイルができる。それ以外の場所のプロジェクトでも README.txt や README など、ファイル名がすべて大文字になっているものをよく見かける。

なんか気持ち悪いなぁ、って思ってました。
readme でいいじゃん、と。


詳解 Linuxカーネル 第3版

詳解 Linuxカーネル 第3版

調べてみた

README - Wikipedia, the free encyclopedia
英語版 Wikipedia にそのままジャストな答えが書かれていました。

It is traditionally written in upper case so that on case-preserving environments using an ASCIIbetical ordering, the name will appear near the beginning of a directory listing (since upper-case letters sort before lower-case letters in ASCIIbetical ordering).

意訳するとこんな感じ。

伝統的に、README のファイル名には大文字が使われる。
ASCII文字コード順の整列を採用している環境では、このような名前のファイルは優先的にリスト上部に表示される。

ほぅほぅなるほど~~。
たしかにASCII文字コードでは大文字のほうが小文字よりも小さい値を持っているのだ。
ASCII - Wikipedia, the free encyclopedia

0x41 A   0x61 a
0x42 B   0x62 b
0x43 C   0x63 c
0x44 D   0x64 d
 
0x58 X   0x78 x
0x59 Y   0x79 y
0x5A Z   0x7A z

確認してみる

CentOS 6.5 Bash にて。

$ ls -1
abc.txt
hoge.txt
README
xyz.txt

あれ…? …どうやら並びは LANG に依存するらしい LC_COLLATE (結果として LC_ALL や LANG も影響する) に依存するらしい。(※id:m-nazeさんにご指摘いただき訂正しました。ありがとうございます。)

$ echo $LC_ALL
(出力なし)
$ echo $LC_COLLATE
(出力なし)
$ echo $LANG
en_US.UTF-8

en_US.UTF-8 でした。

LANG=C にしてみる

$ LANG=C ls -1
README
abc.txt
hoge.txt
xyz.txt

ASCII文字コード順になりました。
たしかに README という大文字のファイルが先頭に表示された。目立つ!

とりあえず理由のある慣習でした

別にこれの恩恵を受けることは僕個人としてはあまりありませんが、慣習が慣習として存在する理由を理解しておくと、心晴れやかに慣習に従うことができますね。

追加情報:LC_COLLATE

上でも訂正を加えてありますが、記事を書いた当初は挙動が LANG に依存する、と思っていましたが、正確には LC_COLLATE でした。(結果として LC_ALL や LANG も影響する)

はてなブックマークのコメント

id:m-naze
更に重要なファイルには '!' とか '_' とか数字とか付けたりするバッドノウハウ。/正確には LANG じゃなくて LC_COLLATE によって strcoll(3) の挙動が切り替わるんですよね。 2014/05/09

情報ありがとうございます。

Man page of STRCOLL

strcoll - 現在のロケールを使用して二つの文字列を比較する

strcoll() 関数は二つの文字列 s1 と s2 を比較する。… 比較は、プログラムの現在のロケールLC_COLLATE カテゴリに応じて 解釈された文字列に基づいて行われる (setlocale(3) 参照)。

Man page of SETLOCALE


LC_COLLATE
正規表現のマッチング (範囲表現と等価クラスのマッチングを決定する) と文字列の照合 (collation)

locale が "" の場合、ロケールの各部分の設定には環境変数が参照される。 その詳細は実装依存である。 glibc の場合、まず最初に (どんな category に対しても) 環境変数 LC_ALL が検査される。 次にカテゴリ (category) と同じ名前の環境変数 (LC_COLLATE, LC_CTYPE, LC_MESSAGES, LC_MONETARY, LC_NUMERIC, LC_TIME) が検査され、最後に環境変数 LANG が検査される。 最初に見つかった環境変数を使用する。 その値がロケール指定として正しくなければ、ロケールは変更されず、 setlocale() は NULL を返す。

再確認

$ LC_COLLATE=C ls -1
README
abc.txt
hoge.txt
xyz.txt

なーるほどーー。情報は発信してみるものです。より詳しい方からの情報が得られて勉強になりました。

環境にもよるけどだいたい LC_ALL → LC_COLLATE → LANG という評価順っぽいので、例えば既に LC_ALL が設定されていればそっちが優先されることが多いです。

});