フォルダ(ディレクトリ)操作を行うには、「Dirクラス」を利用します。Perlのように「opendir」関数や「readdir」関数ではなく、Dirオブジェクトのメソッドとして、「openメソッド」や「eachメソッド」などを利用することになります。
まず、フォルダは「openメソッド」でオープンします。引数はディレクトリですが、ディレクトリの「\」記号は「/」に変更します。したがって、
c:\Ruby\doc\ruby\ruby-1.9.1\
というフォルダは、
c:/ruby/doc/ruby/ruby-1.9.1/
と指定します。openメソッドによって、一度に変数にセットされるため、1件ずつ処理するには、「eachメソッド」を利用します。
Dirオブジェクトの「openメソッド」は、フォルダ内のファイルの他に、サブディレクトリや自分自身である「.」や親ディレクトリである「..」を出力します。このうち、ディレクトリ以外の通常のファイルだけを判定するためにRubyには「FileTestモジュール」があります。「FileTestモジュール」は、
FileTest.file?(ファイル名)
の形式でファイル(フォルダを除く)かどうかが判定できます。判定する場合は、フルパスでファイル名を指定する必要があるので、「$dir_name」に初期値としてフォルダ名をセットしておいたものをつけて、指定します。
なお、フォルダ名やファイル名にアクセント記号のついた半角アルファベットが含まれていると、正常に出力されない場合がありますので、注意してください
実際に応用する場合は、入出力データのファイル名等変更して利用します。
# readdir.rb # 内容 : フォルダ内のファイル名出力 # Copyright (c) 2002-2015 Mitsuo Minagawa, All rights reserved. # (minagawa@fb3.so-net.ne.jp) # 使用方法 : c:\>ruby readdir.rb # # ファイル名を出力するフォルダ dir_name = "c:/ruby19/doc/ruby/ruby-1.9.1/" filename = Dir.open(dir_name) # 出力ファイル out1_file = open("filename.txt","w") # 主処理 filename.each { |name| fullname = dir_name + name if (FileTest.file?(fullname)) out1_file.print name,"\n" elsif (FileTest.directory?(fullname)) out1_file.print name,"\n" end } # ファイルのクローズ out1_file.close
ファイルの出力
fullname = dir_name + name if (FileTest.file?(fullname)) out1_file.print name,"\n" elsif (FileTest.directory?(fullname)) out1_file.print name,"\n" end
「fullname = dir_name + name」とすることで、ドライブ名やフォルダ名のついたファイル名になります。こうしたファイル名にすることで、「if (FileTest.file?(fullname))」によって通常のファイルかどうかが判定できます。また、フォルダ(ディレクトリ)かどうかを判定するには「elsif (FileTest.directory?(fullname))」で判定できます。特定の拡張子のファイル名だけにしたい場合は、以下のようにします(以下は拡張子が"html"の場合です)。
if (/\.html/ =~ name) out1_file.print name,"\n" end
また、フォルダ名やファイル名に全角文字を含む場合は、$KCODEやマジックコメントを使います。詳しくは[2-1-5.スクリプトの中で漢字を使う]を参照してください。
ChangeLog COPYING COPYING.ja GPL LEGAL LGPL README README.EXT README.EXT.ja README.ja
. .. ChangeLog COPYING COPYING.ja doc ext GPL instRuby.rb LEGAL LGPL MANIFEST misc mkconfig.rb README README.EXT README.EXT.ja README.ja Rubytest.rb sample ToDo
上記は特定のフォルダだけを対象にしたものですが、フォルダの中にサブフォルダが存在する場合、サブフォルダの配下にあるファイルも含めたファイル名を出力するスクリプトは以下のようになります。
サブフォルダの配下にあるファイルも含めたファイル名を出力しますので、「再帰処理」を行います。下記の例では、"c:\ruby\doc\ruby\ruby-1.9.1\"のフォルダにあるファイルをサブフォルダも含めて、出力しています。実際に応用する場合は、入出力データのファイル名等変更して利用します。
# readdir2.rb # 内容 : フォルダ内のファイル名出力 # Copyright (c) 2002-2015 Mitsuo Minagawa, All rights reserved. # (minagawa@fb3.so-net.ne.jp) # 使用方法 : c:\>ruby readdir2.rb # # ファイル名を出力するフォルダ dir_name = "c:/ruby/doc/ruby/ruby-1.9.1/" # 中間ファイルのオープン out1_file = open("temp.txt","w") # フォルダ内の処理(再帰処理) def s_file_name(dir_name,out1_file) file_name = Dir.open(dir_name) file_name.each { |name| # 通常のファイルの場合 if (FileTest.file?(dir_name + name)) out1 = [name,dir_name].join("\t") out1_file.print out1,"\n" # フォルダの場合(カレントフォルダと親フォルダを除く) elsif ((name != ".") && (name != "..")) sv_dir_name = dir_name dir_name = dir_name + name + "/" # サブフォルダ内の処理(再帰処理) s_file_name(dir_name,out1_file) # カレントフォルダに戻る dir_name = sv_dir_name end } end # 主処理 s_file_name(dir_name,out1_file) # ファイルのクローズ out1_file.close # # 中間ファイルを全部読み込む。 in1_file = IO.readlines("temp.txt") # 出力ファイルのオープン out1_file = open("filename.txt","w") # ソートキーの入っている項目番号 sortitem = [1,0] # ソートキーをセットするハッシュのキー hash_key = nil # ソートするレコードをセットするハッシュ sort_rec = Hash.new # ソートキーとなる項目番号からソートキーとなる文字列を作っておく。 #recno番目のレコードがrecordである。 in1_file.each_with_index {|record,recno| record.chomp! # 入力ファイルをタブで分解する。 in1 = record.split("\t",-1) #ソートキーとなる項目の内容をタブで連結してハッシュのキーとする。 hash_key = " " sortitem.each {|i| hash_key += in1[i].downcase + "\t" } # 同じ値を持つキーが複数存在する場合に以下のように指定する。 hash_key += sprintf("%08d",recno) # レコードをハッシュの値としてセットする。 sort_rec[hash_key] = record } # ハッシュのキーをソートし、キー順にレコードを出力する。 sort_rec.sort_by{|key| key }.each{|key,value| temp = value.split("\t") # out1 = temp[1] + temp[0] # out1_file.print out1,"\n" out1_file.print value,"\n" } # ファイルのクローズ out1_file.close
フォルダの指定
dir_name = "c:/ruby/doc/ruby/ruby-1.9.1/" out1_file = open("temp.txt","w") s_file_name(dir_name,out1_file) out1_file.close
dir_nameには出力するフォルダをドライブ名も含めて、指定します。ただし「\」は「/」に変えます。そして、dir_nameと出力するファイルハンドルを引数にして、サブプログラムを呼び出します。
サブプログラムの初期値設定
def s_file_name(dir_name,out1_file) file_name = Dir.open(dir_name)
サブプログラムの内部では、引数の「dir_name」を使用してファイル名を一度に呼び出し、file_nameにセットします。file_nameは一次元の配列として、ファイル名がそれぞれの要素にセットされます。
ファイル名出力
file_name.each { |name| # 通常のファイルの場合 if (FileTest.file?(dir_name + name)) out1 = [name,dir_name].join("\t") out1_file.print out1,"\n" # フォルダの場合(カレントフォルダと親フォルダを除く) elsif ((name != ".") && (name != "..")) sv_dir_name = dir_name dir_name = dir_name + name + "/" # サブフォルダ内の処理(再帰処理) s_file_name(dir_name,out1_file) # カレントフォルダに戻る dir_name = sv_dir_name end }
フォルダ内で通常のファイル(サブフォルダ以外)であれば、ファイル名とフォルダ名をあわせて出力します。また、サブフォルダの場合はカレントフォルダと親フォルダを除いて、再帰処理でサブフォルダ内の処理を行います。
再帰処理を行う場合は、カレントフォルダ名をmy宣言をした変数に保存します。これにより、サブフォルダ内の処理を終わった後、元のフォルダの処理が続行できるようになります。ファイル名の並べ替え
# 中間ファイルを全部読み込む。 in1_file = IO.readlines("temp.txt") # 出力ファイルのオープン out1_file = open("filename.txt","w") # ソートキーの入っている項目番号 sortitem = [1,0] # ソートキーをセットするハッシュのキー hash_key = nil # ソートするレコードをセットするハッシュ sort_rec = Hash.new # ソートキーとなる項目番号からソートキーとなる文字列を作っておく。 #recno番目のレコードがrecordである。 in1_file.each_with_index {|record,recno| record.chomp! # 入力ファイルをタブで分解する。 in1 = record.split("\t",-1) #ソートキーとなる項目の内容をタブで連結してハッシュのキーとする。 hash_key = " " sortitem.each {|i| hash_key += in1[i].downcase + "\t" } # 同じ値を持つキーが複数存在する場合に以下のように指定する。 hash_key += sprintf("%08d",recno) # レコードをハッシュの値としてセットする。 sort_rec[hash_key] = record } # ハッシュのキーをソートし、キー順にレコードを出力する。 sort_rec.sort_by{|key| key }.each{|key,value| temp = value.split("\t") # out1 = temp[1] + temp[0] # out1_file.print out1,"\n" out1_file.print value,"\n" }
出力したファイルをフォルダ名順のファイル名順で並べ替えています。ドライブ名とフォルダ名つきのファイル名を出力したい場合は、出力する箇所を以下のように変更します。
# ハッシュのキーをソートし、キー順にレコードを出力する。 sort_rec.sort_by{|key| key }.each{|key,value| temp = value.split("\t") out1 = temp[1] + temp[0] out1_file.print out1,"\n" }
ChangeLog c:/ruby/doc/ruby/ruby-1.9.1/ COPYING c:/ruby/doc/ruby/ruby-1.9.1/ COPYING.ja c:/ruby/doc/ruby/ruby-1.9.1/ GPL c:/ruby/doc/ruby/ruby-1.9.1/ LEGAL c:/ruby/doc/ruby/ruby-1.9.1/ LGPL c:/ruby/doc/ruby/ruby-1.9.1/ README c:/ruby/doc/ruby/ruby-1.9.1/ README.EXT c:/ruby/doc/ruby/ruby-1.9.1/ README.EXT.ja c:/ruby/doc/ruby/ruby-1.9.1/ README.ja c:/ruby/doc/ruby/ruby-1.9.1/ ChangeLog-1.8.0 c:/ruby/doc/ruby/ruby-1.9.1/doc/ ChangeLog-YARV c:/ruby/doc/ruby/ruby-1.9.1/doc/ forwardable.rd c:/ruby/doc/ruby/ruby-1.9.1/doc/ forwardable.rd.ja c:/ruby/doc/ruby/ruby-1.9.1/doc/ NEWS-1.8.7 c:/ruby/doc/ruby/ruby-1.9.1/doc/ README c:/ruby/doc/ruby/ruby-1.9.1/doc/ shell.rd c:/ruby/doc/ruby/ruby-1.9.1/doc/ shell.rd.ja c:/ruby/doc/ruby/ruby-1.9.1/doc/ README c:/ruby/doc/ruby/ruby-1.9.1/doc/bigdecimal/ ・・・・・<以下略>
c:/ruby/doc/ruby/ruby-1.9.1/ChangeLog c:/ruby/doc/ruby/ruby-1.9.1/COPYING c:/ruby/doc/ruby/ruby-1.9.1/COPYING.ja c:/ruby/doc/ruby/ruby-1.9.1/GPL c:/ruby/doc/ruby/ruby-1.9.1/LEGAL c:/ruby/doc/ruby/ruby-1.9.1/LGPL c:/ruby/doc/ruby/ruby-1.9.1/README c:/ruby/doc/ruby/ruby-1.9.1/README.EXT c:/ruby/doc/ruby/ruby-1.9.1/README.EXT.ja c:/ruby/doc/ruby/ruby-1.9.1/README.ja c:/ruby/doc/ruby/ruby-1.9.1/doc/ChangeLog-1.8.0 c:/ruby/doc/ruby/ruby-1.9.1/doc/ChangeLog-YARV c:/ruby/doc/ruby/ruby-1.9.1/doc/forwardable.rd c:/ruby/doc/ruby/ruby-1.9.1/doc/forwardable.rd.ja c:/ruby/doc/ruby/ruby-1.9.1/doc/NEWS-1.8.7 c:/ruby/doc/ruby/ruby-1.9.1/doc/README c:/ruby/doc/ruby/ruby-1.9.1/doc/shell.rd c:/ruby/doc/ruby/ruby-1.9.1/doc/shell.rd.ja c:/ruby/doc/ruby/ruby-1.9.1/doc/bigdecimal/README ・・・・・<以下略>