試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

Pythonで特定のディレクトリ以下のファイルとディレクトリを一覧・特定ディレクトリ以下を全削除

os.walk()を使用することで、そのディレクトリ以下のファイルやディレクトリを全て検索することができ、サブディレクトリ以下もたどってくれる。
結果は3つの要素によるタプル型で返されて、最初の要素が現在たどっているディレクトリで、残りがディレクトリとファイルの一覧になっている。全てのファイルとディレクトリに対して操作を行う場合、下のように反復処理する。
(2015/1/6)リファレンスのリンク先を修正し、サンプルコードもPython 3で動作することなどを目的に大幅に修正した。

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

from __future__ import print_function

import locale
import sys
import os

def error_cb (e):
  """
  エラー発生時の処理
  ここで手動で例外を発生させることで処理を中断することができる
  """
  print ('Could not open "{0}" [{1}]: {2}'.format (e.filename, e.errno, e.strerror), file=sys.stderr)
  # エラーが発生しても処理を続けたい場合は
  # 下のraise文を記述せず、メイン処理のtry-exceptも外す
  raise OSError (e)


# メイン処理
locale.setlocale (locale.LC_ALL, '')
if len (sys.argv) < 2:
  print ('USAGE: {0} [DIR...]'.format (__file__))
else:
  try:
    for topdir in sys.argv[1:]:
      print ('----- {0} (topdown=True) -----'.format (topdir))
      # 浅い階層から深い階層へたどる
      for root, dirs, files in os.walk (topdir, onerror=error_cb):
        for d in dirs:
          print ('dir: {0} ({1} + {2}) '.format (os.path.join (root, d), root, d))  # ディレクトリ
        for f in files:
          print ('file: {0} ({1} + {2})'.format (os.path.join (root, f), root, f))  # ファイル
      # 深い階層から浅い階層へたどる
      print ('----- {0} (topdown=False) -----'.format (topdir))
      for root, dirs, files in os.walk (topdir, topdown=False, onerror=error_cb):
        for d in dirs:
          print ('dir: {0} ({1} + {2}) '.format (os.path.join (root, d), root, d))
        for f in files:
          print ('file: {0} ({1} + {2})'.format (os.path.join (root, f), root, f))
  except OSError as e:
    sys.exit (1)

「topdown=False」を指定すると、深い階層から浅い階層へとたどっていく。下はこれを使用した例として、指定ディレクトリ以下のファイルとディレクトリを全て削除する。
(2014/6/9)実際にディレクトリ以下の削除を行う際にはshutil.rmtree()が便利。

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

from __future__ import print_function

import sys
import os

# 引数に指定したディレクトリ以下を全て削除
if len (sys.argv) < 2:
  print ('USAGE: {0} [DIR...]'.format (__file__))
else:
  for topdir in sys.argv[1:]:
    print ('----- {0} -----'.format (topdir))
    for p, dirs, files in os.walk (topdir, topdown=False):
      for d in dirs:
        d_path = os.path.join (p, d)
        if os.path.islink (d_path):
          print ('rm (dir link): {0} ({1} + {2}) '.format (d_path, p, d))
          os.unlink (d_path)  # シンボリックリンク
        else:
          print ('rmdir: {0} ({1} + {2}) '.format (d_path, p, d))
          os.rmdir (d_path)  # ディレクトリ
      for f in files:
        f_path = os.path.join (p, f)
        print ('rm: {0} ({1} + {2})'.format (f_path, p, f))
        os.unlink (f_path)  # ファイル
    print ('rmdir: {0}'.format (topdir))
    os.rmdir (topdir)

参考URL: