R でシェルのコマンドをもう少しお気軽に叩きたい


R で現在のディレクトリーの中身を表示するのに list.files() とか dir() とか面倒くさいので ls だけで何とかしたいというお話です。

ヒントは @hoxo_m 氏のブログ記事『R を終了させる最短コードがおもしろい』にあるように, print 関数にあります。つまり, インタラクティブでオブジェクトを表示する際には print 関数が呼ばれるので, print 関数がシステムコマンドを呼び出すようにしてやれば良いわけです。

使用方法は以下のような感じになります。

以下解説。

print.command は command クラスのオブジェクトに対する print です。これを system 関数に設定することで, command クラスのオブジェクトを R で表示する際には自身を引数とするシステムコマンドが呼ばれます。

そのコマンドを作るのが as.command 関数です。以下のように呼び出します。

as.command(ls)

引数として与えられた式 (この場合は ls) の文字列表現を呼び出し元の環境に同名のオブジェクトとして作成します。つまり ls というオブジェクトが "ls" という文字列を持っていることになります。このオブジェクトはそのままでは character クラスなので, command クラスにしてやります。こうすることで, R インタラクティブ上で表示される際に, print.command が呼び出されるので,コマンドが実行されるという仕組みです。

このままではコマンドにオプションを指定することができないので,オプションを与える仕組みを作ります。最初に考えられるのは command オブジェクトを文字列ではなく関数にするという方法ですが,それでは base パッケージの ls 関数とかぶってしまいますし,オプションを与えないときにも () を付ける必要があります。代わりに [] を用いることで, base パッケージの ls 関数とあまり衝突しないようにさせることができます。

[] の挙動を変えるには, print 関数と同様に, command クラス用の [ 関数を作成します。つまり `[.command` です。最初の引数は command クラスのオブジェクトで,その他をコマンドラインオプションとするために ... をパラメーターに指定します。そのまま system 関数の結果を返すようにすると,リターンコードがインタラクティブ上に表示されてしまいますので,それを防ぐために何も表示しないための dev.null クラスを別途作成し, print で何も表示しないようにしています。

ls["-l", "/"] のように文字列を与えるのが若干微妙ですが, substitute... に対して最初の式しかとることができず, ..1 のような番号付き表現はとることができないようなので,文字列を与えるところで妥協しています。

[2015-01-19 02:00 追記] せっかくなのでパッケージ化しました → RaaS

参考文献