開発

ディレクトリ構造だけ再帰的に取得する

新しいシステムを作るときに既存システムを参考にするけど古すぎてドキュメントがない、既存システムを他サーバに移設するためにディレクトリ情報を取得したい、とりあえずディレクトリ構造がわからないで調べなくてはならない。あるいはディレクトリ構造だけバックアップしたい。そんな需要は滅多に無いのですが遭遇してしまったのでメモしておきます。

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もかなり早いです。

Tags: コマンド
管理人

Recent Posts

CanvaがSerif (Affinity) を買収

私は使ったことがないのですが名前はよく聞…

4週間 ago

Serifのスプリングセール – アドオンが50%オフ

Affinity Photoなどレタッチ…

2か月 ago

音声がロボットのようになるときの対処

リモート会議などでたまに相手の音声がおか…

3か月 ago

Serifのブラックフライデー – 全品40%オフ V1ユーザは更にお得!

恒例のブラックフライデーセールが始まりま…

5か月 ago

[rust] rayonで書き直してみました

前回のコードを元にrayonを使った処理…

6か月 ago

[rust] async-stdで書き直してみました

前回のコードをasync-stdで書き直…

6か月 ago