• 締切済み

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% (4845/10255)
回答No.3

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

  • notnot
  • ベストアンサー率47% (4845/10255)
回答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% (4845/10255)
回答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

  • コマンド「dir」の結果を、テキストに出力

    batファイルを使用して、「dir」コマンドの結果を、既存のテキストファイル「dir.log」に出力したいのですが、実装方法を教えていただけないでしょうか? 詳細: ・dirバッチ:C:\work\dir.bat ・ログファイル:C:\work\dir.log ・dirで出力したいフォルダ:D:\work\配下 以下のリダイレクト?を使用して上書きしたいです。 dir >> dir.log どうか、ご教授お願いいたします。

  • コマンド DIRの動作について

    バッチファイルのDIRコマンドでよく分からない事が あるので、ご存知の方、ご教授願います。 あるフォルダ(仮にC:\test\とします。)の中に1行だけ記述された CSVファイルが大量にあります。 これをCOPYコマンドで1ファイルにまとめたいと思います。 しかし、そのフォルダの中にはサブディレクトリがあり、その中にも COPYコマンドの対象としたいCSVファイルがあります。 COPYコマンドはサブディレクトリまで処理対象としてくれない ようですし、サブディレクトリの数は不特定なので、どうしょうかと 困っていたら、あるWebページを見つけました。 ttp://www.fpcu.jp/dosvcmd/bbs/log/copyxcopy/4-1567.html やりたい事はまさにドンピシャで、そのページのコマンドを 自分流に書き換えつつ、完成したのが、以下のコードです。 MKDIR "C:\test2\" XCOPY "C:\test\*.csv" "C:\test2\" /E /Y for /f %%a in ('dir "C:\test\" /b') do XCOPY "C:\test\\%%a\*.csv" "C:\test2\" /E /Y COPY "C:\test2\*.csv" "C:\test2\log.csv" ※変な所で改行が入って見難くなっていたらゴメンナサイ。 上記、コードで試してみた所、WindowsXPでは問題なく動作しました。 しかし、Windows2000で試してみた所、うまく動きませんでした。 PAUSEコマンドを入れて、どんなコマンドが吐かれているのか見たら サブディレクトリを動的に変えようとしてい%%aの中に「ドライブ」 とか「ボリューム」とか入ってくるのです。最初は意味不明でしたが DIRのbオプションを付けない時に、そういう文字がコマンドプロンプト の画面に表示され、それを取得しているんじゃないかという事に 気づきました。ちなみにWindows2000でもDIR C:\test /bとやると フォルダ名、ファイル名しかコマンドプロンプトの画面には表示されません。 気づいたはいいんですが、解決方法が分かりません。 どなたか、コマンドに詳しい方、ご教授ください。 よろしくお願いします。

  • C++ で DIR コマンド

    MS-DOSプロンプトで dir と入力すれば、フォルダ内の 様子がMS-DOSプロンプトに表示されるけど、 C++ で、MS-DOSプロンプトで dir と入力したのと同じ 様にするにはどういうプログラムを作ればいいのですか? 別の言い方で書くと、実行すればMS-DOSプロンプトが 起動し、dir と入力されて dirコマンドが実行される というファイルを作るソースが知りたいんです。 dirコマンドが実行される対象となるディレクトリは どこでもいいんです。 C++ のプログラムでも、ディレクトリ構造を出力することが 出来ると思うんだけど、MS-DOSプロンプトでやってみたいんです。 どうしてそんなことがしたいのかというと、C++ が難しそうだから という理由なんです。 例えば、ファイルコピーを自動化するプログラムを作る時、 C++ のプログラムの出力をMS-DOSプロンプトへ渡す方法を知っていれば、 MS-DOSプロンプトでのコピーは copy コピー元 コピー先 という簡単な書式だから、ファイルコピーを自動化するプログラムも 簡単に作れそうだなと思ったんです。

  • コマンドプロンプトのdirで見えないファイルの削除

    不正な記号を使ったフォルダ名とファイルが存在し、削除できずに困っています。 現象は以下の通りです。 ・起動時に毎回チェックディスクが行われ、該当のファイル名やフォルダ名が出てくる。 ・エクスプローラーで削除をすると、「ファイルを削除できません。送り側のファイルまたはディスクから読み取れません。」 ・ひとつ上のフォルダごと削除しようとしても、「指定されたファイルが見つかりません。」 ・コマンドプロンプトでdirで見てもファイル/ディレクトリは表示されない。 (「<DIR> .」と「<DIR ..>」のみで0個のファイル、2個のディレクトリと表示) ・ネットで調べたコマンドを使って削除しても「指定されたファイルが見つかりません」「ファイル名、ディレクトリ名、またはボリューム ラベルの構文が間違っています。」で削除できない。   del "\\?\<ドライブ名>:\*****\*****\ファイル名"   rd /s "\\?\<ドライブ名>:\*****\*****\フォルダ名" エクスプローラーのドライブのプロパティ→ツールでチェックディスクを、オプションを両方チェックしてまたは片方ずつで行ってから上の作業をしても同じです。 自分で調べてみてもこれ以上の方法が見つからなかったのですが、削除する方法はあるでしょうか?

  • DOS/V Ver6.xx のDIRコマンド

    MS-DOS/V Ver6.xxのDIRコマンドで教えてください。 オプションなしで、ただ単に  dir のコマンドを打った場合、出力される順番はどういった順番になってるのでしょう?  ファイル名のアルファベット順?  拡張子のアルファベット順?  タイムスタンプ順? 3000個のファイルを持つディレクトリで  dir > list.txt でリダイレクトしてみたところ、上記のいずれでもなかったのですが、DOSはどういった順番で 出力してるのでしょう? よろしくお願いします。

  • cronを使ってis_dir関数がうまく動かない

    cronを使用して、ディレクトリが存在した場合には、あるスクリプトを実行するようなスクリプトを考えています。 【sample.php】 <? $search_dir = "./SCH_Dir"; if(is_dir($search_dir)) { echo "Dir"; } else { echo "Not Dir or Not Exist"; } ?> sample.phpとディレクトリ SCH_Dirは同一の階層に配置してあります。 上記のsample.phpをWeb上で実行すると、出力結果は "Dir" となり、ディレクトリの存在のチェックが出来ています。 このsample.phpをcron設定した場合、出力結果が "Not Dir or Not Exist" となり、存在していない、という結果が返ってきてしまいます。(結果をメールで受けてっています) なぜcronで実行した場合と結果が違うのか、原因が分からず困っています。 どなたか解決法をご教授ください。 宜しくお願いします。

    • ベストアンサー
    • PHP
  • dirに追加されるファイルを別のdirにコピーする

    質問させて頂きます。 OSはFreeBSDです。 あるディレクトリ(以下、dir1)にファイルが作られていきます。ファイルは不定期に作られ、また不定期に削除されていきます。このdir1にファイルが作られたら、別のディレクトリ(以下、dir2)にコピーしていきたいのです。つまり削除されるファイルを別のところにためておきたいのですが、どのような方法があるのかわかりません。 勉強していますが、シェルスクリプトも殆ど書いたことがないので、方法やコマンドなどが想像出来ません。ヒントだけでもいいので教えていただけませんか?

  • コマンドの結果をテキストに出力

    今Linuxを勉強しています。 bashコマンドを入力した結果をテキストに出力するコマンドありますか? winodwsでいうと下記のような内容です。 dir >C:\dir.txt

  • No.1067の『ファイルの削除について』の続き

    あるディレクトリ内のファイル(ファイル名はマシン日付.csvとなっています。例:20040906.csv)を検索し、 今日より90日前の日付を取得し、それ以前のファイルをディレクトリから削除するという操作をしたいと思います。 ただし、ファイル名の20040906の前後に文字がある場合には削除できないようにしたいのです。 -------------------------------------- 以下、EtherskyのNo.1067に対する回答より抜粋 $day = 90; #90日前 $dir = './hoge'; #hogeディレクトリとする ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time-(60*60*24*$day)); #$day日前の日付を求める $del_target = sprintf("%04d%02d%02d",$year+1900,$mon+1,$mday); #yyyymmddの形にする($del_target前を削除対象にする) opendir(DIR,$dir); #ディレクトリを開く @list = grep {/\.csv$/i && -f "$dir/$_"} readdir(DIR); #ディレクトリから拡張子csvでファイルだけを吸い出してリストにする closedir(DIR); #ディレクトリを閉じる foreach (@list){ #リストから一つずつ調べる if(/(\d+)\.csv$/i){ #頭が数字のファイルだったら if($1 lt $del_target){ #$del_targetと比較して該当するなら unlink("$dir/$_"); #削除 } } } -------------------------------------- 上記の場合で試したところ、20040906の前にabcとつけると 削除されてしまいます。 後ろにabcがついている場合には削除されません。 どのようにすれば削除されないようになるでしょうか?

    • ベストアンサー
    • Perl
  • DOSコマンドでVBSで取得した値をセットしたい

    DOSコマンドで VBSで取得した値をセットしたい サーバ上のあるフォルダにファイルが蓄積されています。 2011_07_01.csv 2011_07_02.csv 2011_07_05.csv 2011_08_05.csv 今月(8月)になった時点で、先月分(07月)で且つ_01.csv と_05.csvファイル を削除するコマンドを作ろうとしています。 先月を取得する部分をVBSにし、その値をセットしようとしましたが、セット方法が分かりません。 echo WScript.Echo Right("0" & Month(DateAdd("d",-15,Date)), 2)> C:\tmptest.vbs CALL C:\tmptest.vbs とするとメッセージボックスで'07'と出力されます。 イメージですが、この'07'を変数にセットして、 (SET AAA = C:\tmptest.vbsの出力結果 のような) フォルダ内で ????_%AAA%_01.csv ,????_%AAA%_05.csv にマッチすれば削除するとしたいのですが、 (FOR /R %%A IN (????_%AAA%_01.csv,????_%AAA%_05.csv) DO DEL %%A というかんじで) VBSで取得した値をセットする方法を教えてください。

専門家に質問してみよう