2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

"treeコマンドのディレクトリ内のファイル一覧をソートしたい!"をPythonのsortedのkeyパラメータで

Posted at

#はじめに
Windowsの話です。

treeコマンドは、ディレクトリの構造を木構造形式で見ることができるアレです。

tree.cmd
├─CrystalBeadsCurtain00002
│  │  crystal_bead_curtain_diffuse.tga
│  │  crystal_bead_curtain_transparency.png
│  │  DemoProducts_CrystalBeadsCurtain00002_0001.max
│  │  DemoProducts_CrystalBeadsCurtain00002_0001.rfa
│  │  FRONT_LOD0_DemoProducts_CrystalBeadsCurtain00002.dwg
│  │  PLAN_LOD0_DemoProducts_CrystalBeadsCurtain00002.dwg
│  │  SIDE_LOD0_DemoProducts_CrystalBeadsCurtain00002.dwg
│  │
│  └─SOURCE_DATA
├─ENA101Art00001
│  │  DemoProducts_ENA101Art00001_0001.max
│  │  DemoProducts_ENA101Art00001_0001.rfa
│  │  DemoProducts_ENA101Art00001_render.jpg
│  │  FRONT_LOD0_DemoProducts_ENA101Art00001.dwg
│  │  PLAN_LOD0_DemoProducts_ENA101Art00001.dwg
│  │  SIDE_LOD0_DemoProducts_ENA101Art00001.dwg
│  │
│  └─SOURCE_DATA
│          EN_A_101_A_103_A104_190603.fbx
│

一覧性がいいので、必要なファイルが揃っているかなどを確認したいときに便利です。
自分は割とよく使います。
ただ、ちょっとだけ改善出来たらいいなと思うところがあります。
それが 並び順 についてです。

#Windowsのtreeコマンド
Windowsのtreeコマンドは、Linuxのtreeコマンドと違って、オプションが2つしかありません。
このオプションにソート(並び換え)に関するものはありません。
常に単純な名前順になってしまいます。

もっと見やすく並べられたらなぁというのが希望です。
出来ることなら、重要なファイルから順に並んでくれたらなおいいと思います。

これをPythonでなんとかします。

#ディレクトリの一覧を取得する
まずはディレクトリの一覧を作ります。
こちらの方のブログ記事を参考にしました。

Powershellでディレクトリの一覧

当初、Powershellでそういうことが出来ないかとトライしてみました。
Windows10ではPowershellのウィンドウをとても簡単に "その場所" で開くことが出来ます。
そうするとパスの指定が不要になり、コマンドの実行が非常に簡単だからです。1

ただ、自分がPowershellに慣れてなくて、結局諦めました...。

テストコード
```powershell:pstree.ps1 cls function pstree($path, $level) { if ($path | Test-Path) { foreach($item in (Get-ChildItem $path) ) { Write-Host ("`t"*$level + $item.Name) if($item.PSIsContainer) { pstree $item ($level+1) } } } } pstree "Z:\PROJECTS\MODELS" 0 ```

そもそも、並び替えをどしたらよいのかわかりません。
リストを順番に見ていってスワップするような関数を書くとか?でしょうか。
なんか面倒くさそうな...。

でもPythonならもっと簡単に書けるはず!

Pythonでディレクトリの一覧

Python3で書きました。
pathlibを使用します。

tree.py
from pathlib import Path

def tree(path=None, level=0):
    p = Path(path)
    if p.exists():
        ff = list(p.glob('*'))
        for f in ff:
            print( '{0}{1}{2}'.format('\n' if level == 0 else '' , '\t' * level, f.name.split('\\').pop() ) )
            if f.is_dir():
                tree(f, level + 1)

path = r'Z:\PROJECTS\MODELS'
tree(path, 0)

結果 ↓

_tree.txt
DFC8638BAA
	control.jpg    <--- テクスチャ画像は一番後ろへまとめて並べたい
	DEMO_DFC8638BAA_0001.max
	DEMO_DFC8638BAA_0001.rfa
	DEMO_DFC8638BAA_render.jpg
	DEMO_logo.tga   <--- テクスチャ画像は一番後ろへまとめて並べたい
	DR03-109-01-DFC79.jpg   <--- テクスチャ画像は一番後ろへまとめて並べたい
	FRONT_LOD0_DEMO_DFC8638BAA.dwg
	FRONT_LOD1_DEMO_DFC8638BAA.dwg
	lonseal_lonrium_5116.png   <--- テクスチャ画像は一番後ろへまとめて並べたい dwgの間に入るなんてもってのほか!
	PLAN_LOD0_DEMO_DFC8638BAA.dwg
	PLAN_LOD1_DEMO_DFC8638BAA.dwg
	SIDE_LOD0_DEMO_DFC8638BAA.dwg
	SIDE_LOD1_DEMO_DFC8638BAA.dwg
	SOURCE_DATA
		DFC86-AA15-AA10_rev1.dwg
	SUS_diffuse.png
	SUS_glossiness.png
	SUS_normal.png
	top.jpg   <--- できれば拡張子ごとにきれいに並んでほしい
	fan_alpha.png
	fan_diffuse.png

DFD41AH18AA
	DEMO_DFD41AH18AA_0001.max
	DEMO_DFD41AH18AA_0001.rfa
	DEMO_DFD41AH18AA_render.jpg
	DEMO_logo.tga   <--- テクスチャ画像は一番後ろへまとめて並べたい
	FRONT_LOD0_DEMO_DFD41AH18AA.dwg
	FRONT_LOD1_DEMO_DFD41AH18AA.dwg
	PLAN_LOD0_DEMO_DFD41AH18AA.dwg
	PLAN_LOD1_DEMO_DFD41AH18AA.dwg
	SIDE_LOD0_DEMO_DFD41AH18AA.dwg
	SIDE_LOD1_DEMO_DFD41AH18AA.dwg
	SOURCE_DATA
		DFD41-AH18-AA00_rev2.dwg
		カタログ_P121.pdf
	top.jpg

普通にやると、やっぱり、"いい感じ" に並んでくれないです。 2

この並び順を直すには、globで集めたリストをソートしてやればいいわけです。

#sortedのkeyに自作の関数を指定する

ソートにはsorted を使います。そして keyパラメータに自作の関数を指定します。
無名関数を当てているのをよく見ると思いますが、keyに関数を指定すると並び順を設定できます。

今回は、自分の意図した通りに並んでほしいので、自分ルールを定義します。
自分ルール用の関数の意図としては、"ファイルの種類ごとに並んでほしいんだけど、重要なファイルを先頭に持ってきて!" です。

sort_by_my_rule.py
def sort_by_suffix(f):
    keys = [ 'max', 'rfa', 'dwg', 'dxf', 'jpg', 'jpeg', 'png', 'tga', 'psd', 'mb', 'ma', 'fbx', 'obj', 'fmz', 'fzb', 'bak', 'pdf', 'ms', 'txt', 'bat', 'vbs', 'log', 'zip', 'rar', 'xlsx', 'xls', '.swatches']
    values = list(range(0,len(keys)))
    d = dict(zip(keys, values))
    ext = Path(f).suffix[1:]
    if ext in keys:
        return d[ext]*10
    else:
        return 1000

拡張子の辞書を作って、インデックスを返すようにしました。3

比較できるものを返す関数を定義する

正直なところ、はじめ、どんな関数を作ればいいのかよくわからなかったのですが、
要は数字か文字みたいな比較できるものを返せばいいみたいです。

sort_by_my_rule.py
ff = sorted( list(p.glob('*')) , key=sort_by_suffix )

このようにして出力すると

_tree.txt
DFC8638BAA
	DEMO_DFC8638BAA_0001.max
	DEMO_DFC8638BAA_0001.rfa
	FRONT_LOD0_DEMO_DFC8638BAA.dwg
	FRONT_LOD1_DEMO_DFC8638BAA.dwg
	PLAN_LOD0_DEMO_DFC8638BAA.dwg
	PLAN_LOD1_DEMO_DFC8638BAA.dwg
	SIDE_LOD0_DEMO_DFC8638BAA.dwg
	SIDE_LOD1_DEMO_DFC8638BAA.dwg
	DEMO_DFC8638BAA_render.jpg
	control.jpg
	DR03-109-01-DFC79.jpg
	top.jpg
	lonseal_lonrium_5116.png
	SUS_diffuse.png
	SUS_glossiness.png
	SUS_normal.png
	fan_alpha.png
	fan_diffuse.png
	DEMO_logo.tga
	SOURCE_DATA
		DFC86-AA15-AA10_rev1.dwg

整理されて見やすくなりました。

より使いやすくするには、もうひと工夫必要ですが、とりあえず目的は達成しました。

  1. フォルダウィンドウのアドレスバーにPowershellと入力してEnterすれば、その場所で開きます。cdする必要がありません。ちなみにcmdと入力すればコマンドプロンプトが起動します。

  2. フォルダの中身はBIM、建築CG用のデータで、3Dモデルファイルとテクスチャ画像ファイルです。

  3. 10倍してあるのは、あとでもっと細かいルールを追加する際、間に入れるため

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?