BLOGTIMES
2014/03/13

ls -f と Dir.glob()

  linux  cli  ruby 
このエントリーをはてなブックマークに追加

Linux などで ls -l とするとファイル名はきちんと辞書順で表示されるのに、他のプログラムでディレクトリをなめると出てくる順番がバラバラになるということにはずっと前から気になっていました。例えばタイムスタンプや日付でファイルを生成して、古い方から逐次処理しているつもりが・・・・・・というバグを出してしまったこともあります。

そんなちょっと不思議な挙動の理由がやっと分かったのでメモ。例えば find コマンドの結果やRuby のプログラムで Dir.glob() を使ったりすると下記のような結果になります。

$ mkdir bbb $ mkdir ccc $ mkdir eee $ ls bbb ccc eee $ find . -mindepth 1 -type d ./eee ./bbb ./ccc $ ruby -e 'puts Dir.glob("*")' eee bbb ccc

これについては下記のエントリで ls のソースコードはもちろんのこと、 strace による解析や Perl の内部構造についても詳細に解説されています。これはとても良い教材になりそうです。結論としては ls がデフォルトで、ls が出力結果をソートするようになっているだけということのようです。ちなみにこのソートは -f オプションをつけるとオフにできるとのこと。

ls のソースを読んでプログラマになりました - ablog

こちらも getdents を呼んでいる。Perl の readdir も ls も getdents システムコールを呼んでるけど、ls はソートしていると思われる。ls の man を見ると、デフォルトでアルファベットでソートされ、-f オプションをつけるとソートされないと書かれている。
ls に -f オプションをつけると Perl の readdir と同じ順になった。

試しに ls に -f をつけてみると、find や Dir.glob() の結果と同じになりました。
まだまだプログラマとしては青いことを痛感させられますね。


    トラックバックについて
    Trackback URL:
    お気軽にどうぞ。トラックバック前にポリシーをお読みください。[policy]
    このエントリへのTrackbackにはこのURLが必要です→https://blog.cles.jp/item/6575
    Trackbacks
    このエントリにトラックバックはありません
    Comments
    愛のあるツッコミをお気軽にどうぞ。[policy]
    古いエントリについてはコメント制御しているため、即時に反映されないことがあります。
    コメントはありません
    Comments Form

    コメントは承認後の表示となります。
    OpenIDでログインすると、即時に公開されます。

    OpenID を使ってログインすることができます。

    Identity URL: Yahoo! JAPAN IDでログイン