学生の備忘録なブログ

日々のことを忘れないためのブログです。一日一成果物も目標。技術系はQiitaにあげるように変更しました。

treeコマンドをRustで書いた

勉強のためにtreeコマンドをRustで書いたよ

github.com

treeコマンドの要旨

treeコマンドはlsコマンドの再帰的な表示を木構造で表したものです。

これはこれまで意識したことはなかったのですが、コードを読んで確かに再帰的な処理で事足りるなと思いました。

prefix

prefixに対して空白などを追加していくことでディレクトリを右にずらしていくことにより、再帰的な深さを表すことができます。

Rustでコマンド自作 Treeコマンド編

作業メモ

  • よくわからない。
  • コマンドラインのパーサを使わない予定だったが、正直面倒なので使ったほうがいいのかもしれない。

    • 参考にしているtree-rsはclapを使っている。でもstructoptはclapをラップしている。
    • deriveマクロにも対応していてチュートリアルが押しているので、初心者むけなんだろうと考えずに使うことにする。
  • データを扱うので、構造体にする

    • structoptで引数を構造体optにした。
  • debugマクロを入れることで構造体のprintをできるようにした。

  • どうやって表示するか

prefix + |---- + filename

ここで、fileがディレクトリだった場合、再帰的にもう一度移動してディレクトリを出力する。

  • 必要な関数

    • Treeクラス
      • init関数
        • 最終的にどれくらいのディレクトリ、ファイルがあったかを表示させるため
        • dirCount変数
        • fileCount変数
      • レジスター関数
        • initで初期化した変数をインクリメントする
      • サマリー関数
        • initで定義した変数を最終的に表示する
      • ウォーク関数
        • listdir関数でdirectoriryのエントリーを取得してfilepathesリストに入れる。
        • filepathesをソートする
        • len(filepathes)でindexを取得する
        • indexごとにディレクトリの前に入れる表示させかた、再起のさせかたを変更
        • absolute関数
          • absolute = os.path.join(directory, filepaths[index])
          • directory+ディレクトリエントリ
          • 変数absolute、その時その時の処理をするためのpathを持つ変数
  • ウォーク関数の詳細

if index == len(filepaths) - 1:
    print(prefix + "└── " + filepaths[index])
        if os.path.isdir(absolute):
                self.walk(absolute, prefix + "    ")
        else:
            print(prefix + "├── " + filepaths[index])
            if os.path.isdir(absolute):
                self.walk(absolute, prefix + "│   ")
  1. もし最後ならprefix(初期値"") "└── "

    1. かつabsoluteがディレクトリなら再起でwalk(absolute,prefixに空白を足す)
    2. それ以外なら"├── "
      1. もしabsoluteがディレクトリならwalk(absolute,prefixに"│ "を足す)
  2. filter_map()

  3. prefixをString::from("")で作成する

    • hello.push('w');で後々伸ばせる。
  4. フルパスではなく、ファイル名を表示する

    • let filename = path.file_name().unwrap().to_str().unwrap();

ToDoスタック

  • [x] 構造体optを作る
  • [x] optからpathを表示する
  • [x] pathの前にprefix(階層を表す記号)をどうやって挿入するか調べる。
  • [x] 再起させずに、まずはファイル名の前にprefixと記号を入れてみる。
  • [x] 必要な関数の概要を理解する
    • [x] pythonのコードを読んで必要な関数の概要を理解する
    • [x] rustのコードを読んで必要な関数の概要を理解する
  • [x] vec<>にpathを入れる
    • [x] resultをunwrapする
  • [x] prefixをString::from("")で作成する
  • [x] paths配列の中身をフルパスではなく、ディレクトリorファイル名のみにする。
    • [x] 一番うしろを切り取る方法を調べる。

重要だけど今じゃないToDoスタック

  • [ ] オプションをパースして取得する
  • [ ] .からtreeを始める(treeの根)

参考文献

https://rust-cli.github.io/book/tutorial/cli-args.html https://github.com/kddeisz/tree/blob/master/tree.py https://doc.rust-lang.org/std/path/struct.Path.html https://github.com/sighol/tree-rs https://github.com/alexanderwe/rs-tree