ファイルやディレクトリをSQLライクに検索するコードを書く

ファイルやディレクトリをもっと簡単に検索したいと考える。
やることは簡単だ。
  1. glob.iglob(glob.glob)でファイルやディレクトリを取得する
  2. ファイルやディレクトリに関するデータを取得する
  3. データをSQLiteに投入する
  4. SQLライクに検索する
import sys
import os
from glob import iglob
import sqlite3
from datetime import datetime

if len(sys.argv) < 2:
	print("Usage: python {} 'PATH' ['QUERY']".format(sys.argv[0]))
	sys.exit(0)
path = sys.argv[1]
query = None if len(sys.argv) < 3 else sys.argv[2]
print('[INFO] PATH: {}'.format(path))
print('[INFO] QUERY: {}'.format(query))

fields = ['path','is_file','is_dir','name','extension','directory','abspath','atime','ctime','mtime']

def get_info(path):
	return {
		'path': path,
		'is_file': os.path.isfile(path),
		'is_dir': os.path.isdir(path),
		'name': os.path.split(path)[1],
		'extension': os.path.splitext(path)[1][1:],
		'directory': os.path.split(path)[0],
		'abspath': os.path.abspath(path),
		'atime': datetime.fromtimestamp(os.path.getatime(path)),
		'ctime': datetime.fromtimestamp(os.path.getctime(path)),
		'mtime': datetime.fromtimestamp(os.path.getmtime(path)),
	}

co = sqlite3.connect(':memory:')
c = co.cursor()
c.execute('CREATE TABLE data ('+','.join(['{} NUMERIC'.format(x) for x in fields])+')')
q = 'INSERT INTO data VALUES ('+','.join('?'*len(fields))+')'
for path in iglob(path, recursive=True):
	info = get_info(path)
	c.execute(q,tuple(info.values()))
co.commit()

data = {'hits':0,'docs':[]}
q = 'SELECT {} FROM data'
if query is not None: q += ' WHERE {}'.format(query)
try: data['hits'] = co.execute(q.format('COUNT(*)',query)).fetchone()[0]
except: sys.exit('[ERROR] The query is invalid.')
docs = data['docs']
co.row_factory = sqlite3.Row
for r in co.execute(q.format('*')): docs.append(dict(r))
del co
print(data)
2020/07/14 21:15
タグ