ファイルがあるかないか,読めるか,書けるか,空か,など 指定したファイルの状態を調べるための組み込み関数 test がある。
test
の用法test
は,
test(cmd, file1 [, file2])
の書式で用い,指定したファイル file1 が cmd の要件を満たすかどうかを返す。2つのファイルの 関係を調べるための cmd には第3引数 file2 を与える。
cmd | 働き |
---|---|
?r | 現在の実行uidで読めるか |
?w | 現在の実行uidで書き込めるか |
?x | 現在の実行uidで実行できるか |
?o | 現在の実行uidが所有するファイルか |
?G | 現在の実行gidと同じグループ所有か |
?R | 実 uid で読めるか |
?W | 実 uid で書き込めるか |
?X | 実 uid で実行できるか |
?O | 実 uid が所有するファイルか |
?e | 存在するか |
?s | 0バイトでないか(サイズが返る) |
?f | 普通のファイルか |
?d | ディレクトリか |
?l | シンボリックリンクか |
?p | 名前付きパイプ(FIFO)か |
?b | ブロックデバイスファイルか |
?c | キャラクタデバイスファイルか |
?u | setuidビットがセットされているか |
?g | setgidビットがセットされているか |
?k | stickyビットがセットされているか |
?M | 最終更新時刻を返す |
?A | 最終アクセス時刻を返す |
?C | inode時刻を返す |
以下は第2,第3引数間の比較 | |
?- | 両ファイルが同一か |
?= | 両ファイルの最終更新時刻が等しいか |
?> | file1の 最終更新時刻がfile2より大きい(新しい) |
?< | file1の 最終更新時刻がfile2より小さい(古い) |
test
の利用例実行結果を決まった名前のファイルに保存するようなコマンドを考える。
たとえば,おみくじの結果をカレントディレクトリの fortune.txt
に保存するプログラムがあったとする。
#!/usr/bin/env ruby # coding: euc-jp #Foretune teller - version 0 ftune = %w,大吉 吉 中吉 小吉 半吉 末吉 小凶 凶, outfile = "fortune.txt" srand result = ftune[rand(ftune.length)] open(outfile, "w") do |f| f.printf("今日の運勢は %s\n", result) end STDERR.puts "#{outfile}を見よ。"
このプログラムを最初に起動するときは問題がない。しかし, 実行すると結果ファイルを上書きするので,以下のような問題がある。
chmod
してあるかもしれない改良してみる。
上記2点の改良を施してみよ。
あるディレクトリ以下にあるすべてのファイルに対して特定の処理を 行なうことはしばしば必要となる。そのための手順の流れは 以下のようになる。
特定の処理をメソッド化し,処理対象がディレクトリなら再帰処理を 行なう。以下のプログラムは,指定したディレクトリ (省略時はカレントディレクトリ)以下すべてのファイルに対して, それが通常ファイルならバックアップファイルを作成する。。
#!/usr/bin/env ruby # coding: euc-jp dir = ARGV.shift || "." def cp(from, to, bufsize=8192) open(from, "r") do |src| open(to, "w") do |dest| while s = src.read(bufsize) dest.write s end end end end def bakdir(dir) ext = ".bak" Dir.foreach(dir) do |f| file = File.expand_path(f, dir) case f when ".", ".." # カレントディレクトリと親ディレクトリ next # は飛ばす when %r,#{ext}$, # それが既にバックアップファイルなら next # やはり飛ばす else if test(?d, file) # ディレクトリなら bakdir(file) # 再帰的に自分を呼ぶ elsif test(?f, file) # 通常ファイルなら # バックアップファイル作成 bak = File.expand_path(f+".bak", dir) File.unlink(bak) if test(?e, bak) cp(file, bak) end end end end bakdir(dir)