このBlogは移転しました。今後は aish.dev を御覧ください。

Pythonで学ぶ「詳解 UNIXプログラミング」(その4) 第4章 ファイルとディレクトリ

4.1 指定したファイルの種類を出力する

import sys, os, stat

for filename in sys.argv[1:]:
    print "{0}:".format(filename),
    try:
        st = os.lstat(filename)
    except Exception, e:
        sys.exit("lstat error")
    
    mode = st[stat.ST_MODE]
    
    if stat.S_ISREG(mode):
        print "regular"
    elif stat.S_ISDIR(mode):
        print "directory"
    elif stat.S_ISCHR(mode):
        print "character special"
    elif stat.S_ISLNK(mode):
        print "symbolic link"
    elif stat.S_ISSOCK(mode):
        print "socket"
    else:
        print "** unknown mode **"

stat()関数はosモジュールで定義されているが、stat構造体から値を読み取るための関数はstatモジュールに定義されている。

4.2 ファイルにアクセス可能かチェックする

import sys, os

if len(sys.argv) != 2:
    sys.exit("usage: python scr4.2.py filename")

if os.access(sys.argv[1], os.R_OK):
    print "read access OK"
else:
    sys.exit("access error for {0}".format(sys.argv[1]))

try:
    open(sys.argv[0])
except Exception:
    sys.exit("open error for {0}".format(sys.argv[1]))

print "open for reading OK"

4.3 umask関数の使用例

import os, stat

open("spam", "w")
os.umask(stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH | stat.S_IWOTH)
open("ham", "w")

作成されたファイル spamhamは異なるパーミッションとなる。

4.4 chmod関数の使用例

import sys, os, stat

if len(sys.argv) != 2:
    sys.exit("usage: python scr4.4.py filename")

# turn on set-group-ID and turn off group-execute
st = os.stat(sys.argv[1])
os.chmod(sys.argv[1], (st.st_mode & ~stat.S_IXGRP) | stat.S_ISGID)

stat構造体は、st.st_modeのように属性値としてメンバにアクセスすることもできる。

4.5 ファイルをオープンし、アンリンクする

import os, time

f = open("spam", "w")
os.unlink("spam")

print "file unlinked"
time.sleep(15)
print "done"

4.6 utime()関数の例

import sys, os

for filename in sys.argv[1:]:
    st = os.stat(filename)
    open(filename, "w")
    os.utime(filename, (st.st_atime, st.st_mtime))

4.7 ファイルの種類を数えながら、再帰的にディレクトリ構造を辿る

import sys, os, stat

if len(sys.argv) != 2:
    sys.exit("usage: python scr4.7.py <starting-pathname>")

total = nreg = ndir = nblk = nchr = nfifo = nslink = nsock = 0

def calc(root, fname):
    global total, nreg, ndir, nblk, nchr, nfifo, nslink, nsock

    st = os.lstat(os.path.join(root, fname))
    mode = stat.S_IFMT(st.st_mode)
    
    if mode == stat.S_IFREG:
        nreg += 1
    elif mode == stat.S_IFBLK:
        nblk += 1
    elif mode == stat.S_IFCHR:
        nchr += 1
    elif mode == stat.S_IFIFO:
        nfifo += 1
    elif mode == stat.S_IFLNK:
        nslink += 1
    elif mode == stat.S_IFSOCK:
        nsock += 1
    elif mode == stat.S_IFDIR:
        ndir += 1

for root, dirs, files in os.walk(sys.argv[1]):
    total += len(dirs) + len(files)
    for d in dirs:
        calc(root, d)
    for f in files:
        calc(root, f)

print total
print "regular file:", nreg, nreg*100.0/total
print "directories:", ndir, ndir*100.0/total
print "block special:", nblk, nblk*100.0/total
print "char special:", nchr, nchr*100.0/total
print "FIFOs:", nfifo, nfifo*100.0/total
print "symbolic links:", nslink, nslink*100.0/total
print "sockets:", nsock, nsock*100.0/total

Python再帰的にディレクトリ構造を辿る時は、os.walk()を使用する。ディレクトリにファイルがないとZeroDivisionErrorが発生してしまうが、大目に見ていただきたい。

4.8 chdir()の例

import os
os.chdir("/tmp")
print "chdir to /tmp succeeded."

4.9 getcwd()の例

import os
os.chdir("/tmp")
print "cwd =", os.getcwd()

4.10 st_devとst_rdevを出力する

import os, sys, stat

for filename in sys.argv[1:]:
    st = os.lstat(filename)
    print "dev = {0}/{1}".format(os.major(st.st_dev), os.minor(st.st_dev))
    
    if stat.S_ISCHR(st.st_mode) or stat.S_ISBLK(st.st_mode):
        print " ({0}) rdev = {1}/{2}".format(
            "character" if stat.S_ISCHR(st.st_mode) else "block",
            os.major(st.st_rdev), os.minor(st.st_rdev))