Pythonクックブック(2章)
ファイル操作の続き
ディレクトリの探索(os.walk, fnmatch)
os.walk(top)を実行すると、(dirpath, subdirnames, filenames) を返す。
[kobakoba0723@fedora13-intel64 ~]$ ls -R top/ top/: eggs.txt spam.txt sub top/sub: hoge.data piyo.data >>> import os >>> for (dirpath, subdirs, files) in os.walk('top'): ... print dirpath ... print files, subdirs ... top ['spam.txt', 'eggs.txt'] ['sub'] top/sub ['piyo.data', 'hoge.data'] [] >>>
fnmatchは シェルのワイルドカードを使ったファイル名のマッチングをするモジュール。
fnmatch.fnmatch(name, pattern)はファイル名nameが パターンpattern にマッチした場合 True を返す
この2つを組み合わせると find | grep と同じようなことが出来る。
[kobakoba0723@fedora13-intel64 ~]$ find top/ | grep -e '.*\.txt' -e '.*\.data' top/spam.txt top/eggs.txt top/sub/piyo.data top/sub/hoge.data [kobakoba0723@fedora13-intel64 ~]$
fnmatchはシェルのワイルドカードを解釈し、grepは正規表現を解釈するので実行時の引数が違う。
[kobakoba0723@fedora13-intel64 ~]$ cat findgrep.py import os import fnmatch def find_grep(root, patterns='*'): patterns = patterns.split(';') for (dirpath, subdirs, files) in os.walk(root): files.sort() for name in files: for pattern in patterns: if fnmatch.fnmatch(name, pattern): yield os.path.join(dirpath, name) break if __name__ == '__main__': import sys if len(sys.argv) != 3: print 'Usage: python findgrep.py <top> <pattern>' sys.exit(1) for filename in find_grep(sys.argv[1], sys.argv[2]): print filename [kobakoba0723@fedora13-intel64 ~]$ python findgrep.py 'top' '*.txt;*.data' top/eggs.txt top/spam.txt top/sub/hoge.data top/sub/piyo.data [kobakoba0723@fedora13-intel64 ~]$
拡張子の変更(os.walk, os.rename)
os.rename(src, dst) は mv src dst と同じ。
os.walk と os.rename を組み合わせると、シェルの forループ + mv と同じことが出来る。
[kobakoba0723@fedora13-intel64 ~]$ ls -R top.shell/ top.shell/: eggs.txt spam.txt sub top.shell/sub: hoge.data piyo.data [kobakoba0723@fedora13-intel64 ~]$ for file in $(find top.shell/ -type f | grep .*\.txt) > do > mv $file ${file%%.txt}.data > done [kobakoba0723@fedora13-intel64 ~]$ ls -R top.shell/ top.shell/: eggs.data spam.data sub top.shell/sub: hoge.data piyo.data [kobakoba0723@fedora13-intel64 ~]$
[kobakoba0723@fedora13-intel64 ~]$ cat swapextension.py import os def swap_extension(dir, before, after): if before[:1] != '.': before = '.' + before extension_len = -len(before) if after[:1] != '.': after = '.' + after for (dirpath, subdirs, files) in os.walk(dir): for filename in files: old_filepath = os.path.join(dirpath, filename) new_filepath = old_filepath[:extension_len] + after os.rename(old_filepath, new_filepath) if __name__ == '__main__': import sys if len(sys.argv) != 4: print "Usage: python swapextension.py <rootdir> <before> <after>" sys.exit(1) swap_extension(sys.argv[1], sys.argv[2], sys.argv[3]) [kobakoba0723@fedora13-intel64 ~]$ ls -R top.py/ top.py/: eggs.txt spam.txt sub top.py/sub: hoge.data piyo.data [kobakoba0723@fedora13-intel64 ~]$ python swapextension.py top.py '.txt' '.data' [kobakoba0723@fedora13-intel64 ~]$ ls -R top.py/ top.py/: eggs.data spam.data sub top.py/sub: hoge..data piyo..data [kobakoba0723@fedora13-intel64 ~]$
サーチパスからファイルを探す(os.path)
os.path モジュールはプラットフォームに依存しない共通のパス名操作モジュール
このモジュールを使うと、which コマンドと同じようなことが出来る。
[kobakoba0723@fedora13-intel64 ~]$ which pep8 ~/bin/pep8 [kobakoba0723@fedora13-intel64 ~]$ which pep /usr/bin/which: no pep in (/home/kobakoba0723/bin:/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin) [kobakoba0723@fedora13-intel64 ~]$
今の状態はenv_pathを固定でやってしまっているので、
シェル変数$PATHから値を持って来れるようになれば良いんだけどなぁ。
[kobakoba0723@fedora13-intel64 ~]$ cat searchcmd.py import os def search_command(command, search_path, path_sep=os.pathsep): for path in search_path.split(os.pathsep): candidate = os.path.join(path, command) if os.path.isfile(candidate): return os.path.abspath(candidate) if __name__ == '__main__': import sys if len(sys.argv) != 2: print 'Usage: python searchcmd.py <command>' sys.exit(1) search_cmd = sys.argv[1] env_path = ['/home/kobakoba0723/bin', '/usr/local/bin', '/usr/bin', '/usr/local/sbin', '/usr/sbin', '/sbin'] search_path = os.pathsep.join(env_path) cmd_path = search_command(search_cmd, search_path) if cmd_path: print "Command '%s' found in '%s'" % (search_cmd, cmd_path) else: print "Command '%s' not found in '%s'" % (search_cmd, search_path) [kobakoba0723@fedora13-intel64 ~]$ python searchcmd.py pep8 Command 'pep8' found in '/home/kobakoba0723/bin/pep8' [kobakoba0723@fedora13-intel64 ~]$ python searchcmd.py pep Command 'pep' not found in '/home/kobakoba0723/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin' [kobakoba0723@fedora13-intel64 ~]$
参考サイト
モジュールインデックス@Python 2.6.2 document
- 作者: Alex Martelli,Anna Martelli Ravenscroft,David Ascher,鴨澤眞夫,當山仁健,吉田聡,吉宗貞紀
- 出版社/メーカー: オライリー・ジャパン
- 発売日: 2007/06/26
- メディア: 大型本
- 購入: 11人 クリック: 423回
- この商品を含むブログ (85件) を見る