Ruby ファイルを読み込む(Dir.globなど)順番について

ディレクトリ内のファイルを読み込む順番、気にしたことありますか？
Rubyのファイル読み込み順についての考察です。
環境：ruby 2.3.1p112
macOS 10.13.6 (17G65)

# はじめに
Rubyでディレクトリ内のファイルを処理する際、Dir.globを使います。
カレントのinディレクトリに
[txtファイル20個]
と
[その他のうんこファイル１万個]
があるとします。

txtファイルだけを処理したい場合はこうです。

```ruby:Ruby
Dir.glob('./in/*.txt').each do |fn|
  puts fn
end
```
で結果はこうです。

```:Result
./in/180726_152833_118036_016.txt
./in/180726_152833_118673_017.txt
./in/180726_152833_111733_006.txt
./in/180726_152833_116294_013.txt
./in/180726_152833_119965_020.txt
./in/180726_152833_113602_009.txt
./in/180726_152833_109057_002.txt
./in/180726_152833_116926_014.txt
./in/180726_152833_119551_019.txt
./in/180726_152833_114285_010.txt
./in/180726_152833_109710_003.txt
./in/180726_152833_115679_012.txt
./in/180726_152833_112946_008.txt
./in/180726_152833_111092_005.txt
./in/180726_152833_115039_011.txt
./in/180726_152833_107647_001.txt
./in/180726_152833_112327_007.txt
./in/180726_152833_119093_018.txt
./in/180726_152833_117478_015.txt
./in/180726_152833_110460_004.txt
```
勘の鋭い方はお気づきかもしれませんが、
./inディレクトリにあるtxtファイルのファイル名は
「日付＿時刻＿マイクロ秒＿番号.txt」
すなわち
「ファイルが生成された時刻がファイル名」
になっています。

ということは、、、、
# ファイルが生成された順番に処理されてないじゃん！
順番に処理しなきゃなんない瞬間（とき）ってあるんだよ。
お父さんびっくりだよ…。

# 何はともあれgoogle
[glob で取得したファイル一覧の順番は保証されるのか](https://qiita.com/kyoshidajp/items/9faafd123a9d52a98cbb)
ここによると
Ruby(2.4.2)順番は保証されるかは…不明…。

[Does Dir.glob guarantee the order?](https://stackoverflow.com/questions/6220753/does-dir-glob-guarantee-the-order)
海外の方も気にしておられるようですが、OSによるよ！とか。悲しい…。

# あんた、あの娘の何なのさ
じゃあDir.globの順番ってなんなのさ！この泥棒猫！ハアハア。
といいたいところですが、グッとこらえてgoogle。
[フォルダー名の読み込み順番について](https://teratail.com/questions/105872)
に

```:godanswer
ls -f で実際に取得した順番で表示されます。
```
との回答がありました。

ではでは

```sh:sh
ls -f ./in
.                             180726_152833_114285_010.txt
..                            180726_152833_109710_003.txt
180726_152833_118036_016.txt  180726_152833_115679_012.txt
180726_152833_118673_017.txt  180726_152833_112946_008.txt
180726_152833_111733_006.txt  180726_152833_111092_005.txt
180726_152833_116294_013.txt  180726_152833_115039_011.txt
180726_152833_119965_020.txt  180726_152833_107647_001.txt
180726_152833_113602_009.txt  180726_152833_112327_007.txt
180726_152833_109057_002.txt  180726_152833_119093_018.txt
180726_152833_116926_014.txt  180726_152833_117478_015.txt
180726_152833_119551_019.txt  180726_152833_110460_004.txt
```
ほ、ほんまや！

# これは何の順番？
先程のTeratailの回答には「物理エントリ」順との回答もあります。
[ページテーブル](https://ja.wikipedia.org/wiki/%E3%83%9A%E3%83%BC%E3%82%B8%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB)
ストレージに記憶（ページング）されている順ということかな…。
計算機的にはその方がいいのかもしれんが、人間にとっては困るんだyo!

##### **じゃあDir:glob使えねーじゃん**
# 初心に帰り、ls -aを使ってみる
ということで一旦Dir.globから脱退してみましょう。
globeから脱退したYOSHIKIのように。

```ruby:Ruby
  files = `ls -a ./in`.split("\n")
  files.each do |f|
    puts f if /.*\.txt$/ =~ f
  end
```
Dir.globがls -fで取得したファイル順だっつーのなら、逆転の発想。
バッククォート記法でls -aして取得したファイルをsplitして配列化してeachします。

```:Result
180726_152833_107647_001.txt
180726_152833_109057_002.txt
180726_152833_109710_003.txt
180726_152833_110460_004.txt
180726_152833_111092_005.txt
180726_152833_111733_006.txt
180726_152833_112327_007.txt
180726_152833_112946_008.txt
180726_152833_113602_009.txt
180726_152833_114285_010.txt
180726_152833_115039_011.txt
180726_152833_115679_012.txt
180726_152833_116294_013.txt
180726_152833_116926_014.txt
180726_152833_117478_015.txt
180726_152833_118036_016.txt
180726_152833_118673_017.txt
180726_152833_119093_018.txt
180726_152833_119551_019.txt
180726_152833_119965_020.txt
```
おおっ！ファイル生成順にテキストが処理されているっぽい？？？？
くれないだー！

# はて？このままでいいのか？
ここで１つの疑念が生じます。
##### ** ファイル名順に処理しているのではないのか？ **と。
というわけで、ファイル名の先頭にランダムで３文字のアルファベットを付加してみましょう。
んで、さっきと同じ

```ruby:Ruby
  files = `ls -a ./in`.split("\n")
  files.each do |f|
    puts f if /.*\.txt$/ =~ f
  end
```

(さっきとはファイル生成時刻は違うのでファイル名も違いますよ）

```:Result
AFC_180726_160348_137270_016.txt
BBU_180726_160348_133355_006.txt
CRV_180726_160348_135485_012.txt
DEU_180726_160348_132165_003.txt
FEX_180726_160348_132962_005.txt
FKQ_180726_160348_132576_004.txt
FWJ_180726_160348_138088_018.txt
IRY_180726_160348_134186_008.txt
KMK_180726_160348_134531_009.txt
KQG_180726_160348_136848_015.txt
LCY_180726_160348_133776_007.txt
OXJ_180726_160348_135874_013.txt
RHE_180726_160348_136242_014.txt
SWQ_180726_160348_135171_011.txt
TMT_180726_160348_138645_019.txt
VUA_180726_160348_137680_017.txt
VVM_180726_160348_134863_010.txt
WCV_180726_160348_139066_020.txt
ZSH_180726_160348_131737_002.txt
ZYD_180726_160348_131238_001.txt
```
案の定かよ！
##### **ls -aはファイル名順に読み込むようです。**

# ls -atrではどうよ！
↓ここを参考
[あるディレクトリ下の全ファイルを更新日時の古い順に詳細表示](http://d.hatena.ne.jp/arrowKato/20120711/1342022221)
lsには色んなオプションがあるんだけど、
-atrは「t:更新順」「r:昇順」に並べ替えします。

```ruby:Ruby
  files = `ls -atr ./in`.split("\n")
  files.each do |f|
    puts f if /.*\.txt$/ =~ f
  end
```
これでどうだ！

```:Result
ZYD_180726_160348_131238_001.txt
ZSH_180726_160348_131737_002.txt
DEU_180726_160348_132165_003.txt
FKQ_180726_160348_132576_004.txt
FEX_180726_160348_132962_005.txt
BBU_180726_160348_133355_006.txt
LCY_180726_160348_133776_007.txt
IRY_180726_160348_134186_008.txt
KMK_180726_160348_134531_009.txt
VVM_180726_160348_134863_010.txt
SWQ_180726_160348_135171_011.txt
CRV_180726_160348_135485_012.txt
OXJ_180726_160348_135874_013.txt
RHE_180726_160348_136242_014.txt
KQG_180726_160348_136848_015.txt
AFC_180726_160348_137270_016.txt
VUA_180726_160348_137680_017.txt
FWJ_180726_160348_138088_018.txt
TMT_180726_160348_138645_019.txt
WCV_180726_160348_139066_020.txt
```
おおやったね！

~~# 結論
**Dir.globはファイル更新順には読み込まないので、バッククォート記法でls -atrでやる**
（Dir.globにオプションがあればいいのに...)~~

# 投稿後にコメントを受けた結論
ここまでやってアレですが、投稿後、[knu](https://qiita.com/knu)さんにコメントをいただきました。

```:godanswer
名前の辞書順: Dir.glob(pattern).sort
生成順: Dir.glob(pattern).sort_by { |fn| File.birthtime(fn) }
更新順: Dir.glob(pattern).sort_by { |fn| File.mtime(fn) }

のように自分でソートする、が答えです。
```
え！俺アホやん...。

```ruby:Ruby
  files = Dir.glob('./in/*.txt').sort_by { |fn| File.birthtime(fn) }
  files.each {|fn| puts fn}
```
```:Result
ZYD_180726_160348_131238_001.txt
ZSH_180726_160348_131737_002.txt
DEU_180726_160348_132165_003.txt
FKQ_180726_160348_132576_004.txt
FEX_180726_160348_132962_005.txt
BBU_180726_160348_133355_006.txt
LCY_180726_160348_133776_007.txt
IRY_180726_160348_134186_008.txt
KMK_180726_160348_134531_009.txt
VVM_180726_160348_134863_010.txt
SWQ_180726_160348_135171_011.txt
CRV_180726_160348_135485_012.txt
OXJ_180726_160348_135874_013.txt
RHE_180726_160348_136242_014.txt
KQG_180726_160348_136848_015.txt
AFC_180726_160348_137270_016.txt
VUA_180726_160348_137680_017.txt
FWJ_180726_160348_138088_018.txt
TMT_180726_160348_138645_019.txt
WCV_180726_160348_139066_020.txt
```
なるほど〜。これでスッキリ！