新しいシステムを作るときに既存システムを参考にするけど古すぎてドキュメントがない、既存システムを他サーバに移設するためにディレクトリ情報を取得したい、とりあえずディレクトリ構造がわからないで調べなくてはならない。あるいはディレクトリ構造だけバックアップしたい。そんな需要は滅多に無いのですが遭遇してしまったのでメモしておきます。
3つほど取得方法を考えました。
というのもディレクトリ以外にも通常ファイルが10万以上あり、速度面でものすごく時間がかかった為です。
それぞれ Solaris、Linuxで検証してみました。
lsコマンド
# Solaris ls -R [target_dirs] | sed -n -e 's/:$//p' # Linux /bin/ls -fR [target_dirs] | sed -n -e 's/:$//p'
速度を上げるためLinuxでは、fオプションでソートを無効にしています。Solarisは再帰的な取得の際にfオプションを指定できなかったので遅いです。
/bin/ls としているのはaliasでカラー表示するオプションが指定されているケースがあるので速度面で余計な事をさせない為です。
シンボリックリンク先にディレクトリがある場合も考慮したコマンドは下記に通りになります。
# Solaris ls -RL [target_dirs] | sed -n -e 's/:$//p' # Linux /bin/ls -fRL [target_dirs] | sed -n -e 's/:$//p'
ただし、出力結果からどれがシンボリックリンクなのか判別することはできません。
findコマンド
# Solaris find [target_dirs] -type d # Linux find [target_dirs] -type d
findコマンドはソートしない動きだったはずです。
シンボリックリンク先にディレクトリがある場合も考慮したコマンドは下記に通りになります。
# Solaris find [target_dirs] -type d find [target_dirs] -type l // find コマンドのバージョンによっては-type d,lという書き方ができるようです # Linux find [target_dirs] -xtype d
Solarisはxtypeオプションが無いので分けて実行することで取得します。キャッシュがあるとはいえ2回実行するので遅いです。
xtypeオプションを使った結果はシンボリックリンクの判別は可能です。
と、書いたのですが別の環境で試すと区別なく表示されました。find [target_dirs] -xtype d -exec ls -dF {} \;
で区別できると思います。上記のコマンドもこの方法でできるでしょう?
treeコマンド
# Solaris N/A # Linux tree -dfiUn --noreport [target_dirs] | sed -e '/->/d'
treeコマンドはSolarisには標準インストールされません。Linuxでもディストリビューションによっては標準でインストールされていないかもしれません。
デフォルトでシンボリックリンク先の情報まで出てしまいます。抑制するオプションはわかりませんでした。なのでsedコマンドでフィルタリングしています。
シンボリックリンク先にディレクトリがある場合も考慮したコマンドは下記に通りになります。
# Solaris N/A # Linux tree -dfiUn --noreport [target_dirs]
デフォルトの結果からシンボリックリンクの判別は可能です。
速度面について
試したSolaris環境上では違いはそれほどありませんでした。
Linux上では、lsコマンド <<<<< find コマンド < treeコマンドの順で短かったです。
フィルタリング処理をパイプで並列処理できているのが効いているのかもしれません。find コマンドとtreeコマンドはそれ程差はありませんでした。
まとめ
シンボリックリンクの情報を気にする場合はfind コマンドとtreeコマンドになるでしょう(そもそも調査目的なので)。
両方の環境で使えるのはfind コマンドなので汎用性があります(しかしオプションは共通ではない)。
上記コマンドは単純にディレクトリ情報を表示する場合も使えますが、リダイレクトでテキストファイルに落とすなど今後の作業の元ネタとして保存しておくことが良いでしょう。
追記
今回の話、全然再帰的な話ではなかったです。こちらを書きながら並行でこちらも書いていたのでタイトルを間違えました。でも、ls -RのRはrecursiveという意味だし、きっとコマンド内部ではサブディレクトリ全てを取得する為に再帰的な処理が行われているのでしょう。プログラムの再帰的な話はこちらをどうぞ。Rustもかなり早いです。