FreeBSDのlsを読む -tオプションを追え!!
ls -tで更新時刻順に並び替えることが出来る。
% ls -t
と、昨日知ったので、ls -tでのソート処理を追ってみることにしました。
cmp.cまで辿り着いた。
cmp.cはその名のとおり、比較関数の定義。mastercmp()から関数ポインタで呼ばれる。
まず、名前順で整列するnamecmpを見る。
int namecmp(const FTSENT *a, const FTSENT *b) { return (strcoll(a->fts_name, b->fts_name)); }
- strcollは
で定義されてる。文字列の比較。Rubyで言うところの<=>演算子。 - 構造体FTSENTは、
で定義されてる。manを参照すべし。 - namecmpは、ファイル構造体FTSENTから、ファイル名を読んで、比較した値を返す。
- 落ち着いて読めばcmp.cにある関数は全て同じ処理をしている。FTSENTを比較する。
- 逆順はrevで、aとbを逆にしただけ。
-tオプションはmodcmpで処理される。
int modcmp(const FTSENT *a, const FTSENT *b) { if (b->fts_statp->st_mtimespec.tv_sec > a->fts_statp->st_mtimespec.tv_sec) return (1); ...(略 }
- 面倒そうな処理を行っているが、落ち着いて読むと、 mtimeで比較してる事がわかる。
- 構造体が入り組んでいるので読みにくい。
-tオプションの比較関数について理解することができました。
もう一度トップダウンで進んでみた。
ls -tを追う。
main
- f_sizesort = 1;
- サイズソートフラグを立てる。
- sortfcn = modcmp;
- sortfcnにmodcmp関数ポインタを代入
- traverse();へ飛ぶ
static void traverse(int argc, char *argv[], int options)
lsのメイン処理にあたる。
- ftsp = fts_open(argv, options, f_nosort ? NULL : mastercmp)) == NULL)
- fts_openは、
で定義されてる。mastercmpが重要どころ。
- fts_openは、
- fts_read()
- 実際の処理(読んでない)
- display()
- 表示を呼ぶ(読んでない)
static int mastercmp(const FTSENT * const *a, const FTSENT * const *b)
比較の処理。
- return (sortfcn(*a, *b));
- mainで指定したsortfcn比較関数を呼ぶ。→modcmp()を呼ぶ
lsの大体の流れが把握出来てきました。
まとめと感想
今回はls -tのソート処理を追ってみました。
- ls -rで逆順表示が出来る。
- ls -Rで再帰的にls出来る。
- lsは関数ポインタだらけ。
- strcoll(3)は便利。
- fts(3)は深い。
オプション1つについて、ボトムアップで読んでいけばそれほど辛くなく読めそうです。
次は、lsの根幹、traverse()を読んでいきたいと思います。
参考
- Manpage of FTS
- fts 関数は、 UNIX ファイル階層をたどるために提供されている。
- かなり便利そう。
- ふつうのLinuxプログラミング 10章 ディレクトリツリーのトラバース
- Manpage of ERR
- エラーメッセージを整形して標準エラー出力に表示する。
- perror(3)とexit(3)を組み合わせたものらしい。便利だが非標準。
- GNU ls