• 締切済み

dirコマンドで取得した結果を加工したい。

お世話になります。 windows上のディレクトリ及びファイル情報を一括で CSV形式で出力したいと思っています。 ご教示ください。 【CSV出力要件】 1カラム目:ディレクトリ若しくはファイルの日付       出力例       (時刻)2017/06/14 17:12 2カラム目:ディレクトリのパス・ファイル名を記載       出力例       (デイレクトリの場合)C:\testdirectory       (ファイルの場合)C:\testdirectory\test.txt 3カラム目:ディレクトリサイズ、ファイルサイズを記載       ディレクトリの場合、配下全ての容量を記載       ファイルの場合、そのファイルサイズを記載 4カラム目:ファイル拡張子を記載 5カラム目:ディレクトリの場合は、Directoryと記載       ファイルの場合は、Fileと記載       ショートカットの場合、shortcutと記載 【設計要件】 ・[dir /S]コマンドで、Windows上のディスク情報を取得する。 ・Linuxのbashで取得結果をCSVに出力する。  ※上記、CSVに出力するファイル名は、windows_dir.csvとする。 ・CSV出力のカラムは前記の通りとする。 ・Dirコマンドで出力される下記を削除する。  1)〇〇個のファイル~バイト(省略)  2)[dir /S]取得結果のファイルの総数:(省略)は削除する。     [dir /S]取得結果の個のファイル~バイト(省略)は削除する。     [dir /S]取得結果の個のディレクトリ~バイトの空き領域(省略)は削除する。  3)[dir /S]取得結果の<DIR>の記述は削除は削除する。  4)ディレクトリの個数をテキストファイルへ出力する    ファイルの個数をテキストファイルに出力する。    個々の拡張子毎にその拡張子の個数をテキストファイルに出力する。    ※上記出力するテキストファイル名は、kakuchoushi.txtとする。  5)[dir /S]取得結果の空白行は削除する。  6)取得時は、開始時刻、終了時刻を記載する。  7)出力結果の文字コードはSJISになっているため、UTF-8に変換する。  8)出力結果の改行コードはCRLFになっているため、LFに変換する。 【留意点】 ・新たに取得し直せばいいのですが、既存の取得済み結果から、  結果を取り出したいと思っております。  ※取得し直しのコメントは無しでお願いいたします。m(_ _)m よろしくお願いいたします。

みんなの回答

  • notnot
  • ベストアンサー率47% (4900/10358)
回答No.3

> ファイル数が多い順で、ソートはできますでしょうか。 count.sort_by{|ext,cnt| -cnt}.each do |ext, cnt| に変えてください。 > 結果を見ると、パスが正常に取得されていないようでした。 こちらでは再現しません。 > 実行されている間、進捗状態を確認したいため、 何百万行もあるんですか?1万行くらいだと一瞬で終わるのですが。 123 / 8888888 のように、全体何行中の何行目処理中とかを出すのは可能ですが、何百万行もあると分母を求めるのに時間が掛かると思いますが。

  • notnot
  • ベストアンサー率47% (4900/10358)
回答No.2

ディレクトリのサイズを求めるのは、今後有用かも知れないので、作ってみました。先の回答に書いた通り、Rubyです。見やすくするため、全角空白でインデントしてあるので、半角空白に直してから実行してください。 > 6)取得時は、開始時刻、終了時刻を記載する。 はパス。取得は既に終わってるんですよね?その時刻はどこに? あと、明確でない部分は適当に解釈してあるので、必要に応じて修正してください。 INFILE="output.txt" OUTFILE="windows_dir.csv" CNTFILE="kakuchoushi.txt" out = {} dirsize = {} dir = nil open(INFILE,"r:Windows-31J:utf-8") do |f| f.each_line do |line|  line.chomp!  case line  when /\A ([A-Z]:.*) のディレクトリ\z/   dir = $1  when %r|\A\d\d\d\d/\d\d/\d\d {2}\d\d:\d\d {4}<DIR> {10}\.\.?\z|  when %r|\A\d\d\d\d/\d\d/\d\d {2}\d\d:\d\d {4}<DIR>|   date,time,_,name = line.split(/\s+/,4)   file = [dir,name].join("\\")   out[file] = [date,time,file,nil,File.extname(name),"Directory"]   dirsize[file] = 0  when /\A\d/   date,time,size,name = line.split(/\s+/,4)   file = [dir,name].join("\\")   size = size.gsub(",","").to_i   ext = File.extname(name)   type = ext == ".lnk" ? "Shortcut" : "File"   out[file] = [date,time,file,size,ext,type]   work = dir   while /\\/ =~ work    dirsize[work] += size if dirsize[work]    work = work.sub(/\\[^\\]+\z/,"")   end  end end end count_dir = 0 count_file = 0 count = Hash.new(0) open(OUTFILE,"w") do |f| out.each do |k,(date,time,file,size,ext,type)|  case type  when "Directory"   size = dirsize[file]   count_dir += 1  when "File"   count_file += 1   count[ext] += 1  end  f.puts "#{date} #{time},#{file},#{size},#{ext},#{type}" end end open(CNTFILE,"w") do |f| f.puts "Directory #{count_dir}" f.puts "File #{count_file}" count.each do |ext, cnt|  f.puts "#{ext},#{cnt}" unless ext == "" end end

s0217071
質問者

補足

notnot様 早速の回答ありがとうございます。 >kakuchoushi.txt はディレクトリ毎じゃなくて、全部トータルですよね? はい。拡張子のテキストは、取得したファイルの トータル(拡張子毎に分類)を指しています。 拡張子の合計は、イメージ通りです。 Excelで整理すればいいだけではあるのですが、 ファイル数が多い順で、ソートはできますでしょうか。 >> 6)取得時は、開始時刻、終了時刻を記載する。 >はパス。取得は既に終わってるんですよね?その時刻はどこに? →認識の通り、既に終わっているのですが、  プログラムが実行された時間の始まりと終わりを指しています。  どの程度、取得時間を要したかを調べたいと思いまして。 実際に実行して、CSV結果を確認したのですが、 下記の結果が出ました。 結果を見ると、パスが正常に取得されていないようでした。 C:\から始まっていれば、C:\も含めて結果に表示させたいです。 【結果内容】 2017/09/30 23:36,\amd64_microsoft-windows-p..ooler-ppc.resources_31bf3856ad364e35_10.0.16299.15_ja-jp_4c865c14fe5dbd9d,0,.15_ja-jp_4c865c14fe5dbd9d,Directory 2017/09/29 23:41,\Microsoft-UtilityVM-Containers-Setup-Package~31bf3856ad364e35~amd64~ja-JP~10.0.16299.15.cat,9029,.cat,File 2007/04/09 22:51,\WS714a382cdf7d304e7e07d0100196cbc5f-635a.html,3738,.html,File 実行されている間、進捗状態を確認したいため、 プログレスバーを表示させたいのですが、 rubyで出力できますでしょうか。 よろしくお願いいたします。

  • notnot
  • ベストアンサー率47% (4900/10358)
回答No.1

明確に書かれていないので、推測ですが、dir /s の結果が既にあって、それだけをインプットとして、元のディスクにはアクセスせず、求めるCSVを出力したいということでしょうか? それはめんどくさいだけでおもしろくないプログラムですね。 >※取得し直しのコメントは無しでお願いいたします。m(_ _)m ということですが、 元のディスクにアクセスして良いなら、下記でほぼ目的のCSVが得られます。 求められないのは、ディレクトリ配下の総サイズで、これだけあとでawkとかExcelとかで計算すれば良いです。 @echo off ( for /f "delims=" %%A in ('dir /s /b') do (  call :ISDIR %%~aA  if errorlevel 1 (   echo %%~tA,%%A,,%%~xA,Directory  ) else if "%%~xA" == ".lnk" (   echo %%~tA,%%A,%%~zA,%%~xA,Shortcut  ) else (   echo %%~tA,%%A,%%~zA,%%~xA,File  ) ) ) > output.txt goto :EOF :ISDIR set A=%1 if "%A:~0,1%" == "d" exit /b 1 exit /b 0 > ・Linuxのbashで取得結果をCSVに出力する。 希望のプログラムは、Bash組み込みの機能だけでは力不足なので、最低限awk、できればPerlかRubyを使わないと困難でしょう。 Rubyでいいなら考えてみます。 kakuchoushi.txt はディレクトリ毎じゃなくて、全部トータルですよね?

関連するQ&A