読者です 読者をやめる 読者になる 読者になる

たけし備忘録

自分の好奇心の赴くままに勉強メモ LL系が大好き Python bash Julia C

Pythonでtreeコマンド実装

python

Windowsにもtreeコマンドがありますがなんとも気に入らなかったので自分で使う用にtreeコマンドを実装しました。
bashだとかCだとかでやったほうが日本語周りはかなり楽なんだろうけど、あえて日本語周りが大変なpythonで練習。
普段あんまりpythonで日本語扱うことが少ないのでいい機会かもしれない。
ということで獣のごとくテキトーに思うまま実装しました。保守性は皆無です。

コマンドプロンプト文字コードはcp932で、Cygwinは確かめて無いので知りません。変えてないからデフォルトのままのはず。

以下よりソースコード

[tree.py]

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import os
import sys

def print_enc(str):
    try:
        print str
    except:
	print str.encode("utf-8")

def tree(path = u".", d = 0, depth = 2, tab=u""):
	#深さの指定で再帰中断
	if d==depth:
	    return
	else:
	    #指定path下(未指定でカレントディレクトリ)のフォルダとファイルを取得
            file_list = []
	    dir_list = []
	    for p in os.listdir(path):
	        if os.path.isfile(path+u"/"+p):
		    file_list.append(p)
		if os.path.isdir(path+u"/"+p):
		    dir_list.append(p)
			
	    #ルートを表示
	    if d==0:
		print u"/%s" % os.getcwd().split("\\")[-1]
		
	    #ファイルの表示
	    for i in xrange(len(file_list)):
		if i!=len(file_list)-1:
		    print tab+u"┣━",
		    print_enc(file_list[i])
		else:
		    if len(dir_list)==0:
			print tab+u"┗━",
			print_enc(file_list[i])
		    else:
			print tab+u"┣━",
			print_enc(file_list[i])

	    #ディレクトリの表示
	    for i in xrange(len(dir_list)):
		if i!=len(dir_list)-1:
		    print tab+u"┣━",
		    print_enc(dir_list[i])
		    tree(path = path+u"/"+dir_list[i], d=d+1, depth=depth, tab=tab+u"┃\t")
		else:
		    print tab+u"┗━",
		    print_enc(dir_list[i])
		    tree(path = path+u"/"+dir_list[i], d=d+1, depth=depth, tab=tab+u"  \t")
            
            return


if __name__=="__main__":
    if len(sys.argv)==2 and sys.argv[1]:
        tree(depth=int(sys.argv[1]))
    else:
        tree()


すんごい見づらいし汚い感じですが一応動きました。
ただ、使うターミナルの設定だとかlessを使った場合だとかで表示がかなり違うのでpythonだとめんどいなぁという印象。3系だと文字周りが簡単になったとか聞くけどどうなんだろうか。
とりあえず

  • 標準モジュールだけで作成
  • 日本語を表示できること(特殊文字は除く)

が実現できたのでいいかな

自分で使う用なのでexe化してしまってテキトーにpath通してしまえばいいや
使い方は(現時点では)

$python tree.py 3

という形で使います。
コマンドライン引数の3は表示するディレクトリの深さです。上の場合3階層まで表示します。1でカレントディレクトリ内を表示します。
デフォルトでは2になっています。

以下より様々な表示結果


[テスト用フォルダ]
f:id:takeshiD:20151218024604p:plain

[コマンドプロンプト(引数:デフォルト)]

python tree.py

f:id:takeshiD:20151218024616p:plain

[コマンドプロンプト(引数:1)]

python tree.py 1

f:id:takeshiD:20151218024620p:plain

[コマンドプロンプト(lessをパイプでつなげた状態)]

python tree.py | less

f:id:takeshiD:20151218024624p:plain

[コマンドプロンプト(引数:4)]

python tree.py 4

f:id:takeshiD:20151218024627p:plain


[Cygwin(引数:デフォルト)]

python tree.py

f:id:takeshiD:20151218024632p:plain

[Cygwin(lessをパイプでつなげた状態)]

python tree.py | less

f:id:takeshiD:20151218024635p:plain


lessをつなげたときだけなぜか特殊文字の♡まで表示出来たのはなんでだろう。しかもコマンドプロンプトの時だけ。
lessコマンドは双方ともCygwin内蔵のlessから持ってきているので文字コードの違いなんだろうなきっと。

コマンドとして使うときディレクトリ指定もできたらいいのですがコマンドライン引数のなんちゃらが面倒でした。
調べた感じだと組み込みでargparseというモジュールがあるらしいのでいずれいじってみたいです。
めんどうだからここまでで終わりにしました。