締切済み

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

  • すぐに回答を!
  • 質問No.9428410
  • 閲覧数125
  • ありがとう数0
  • 気になる数0
  • 回答数3
  • コメント数0

お礼率 20% (24/118)

お世話になります。

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

よろしくお願いいたします。

回答 (全3件)

  • 回答No.3

ベストアンサー率 48% (4321/8861)

> ファイル数が多い順で、ソートはできますでしょうか。

count.sort_by{|ext,cnt| -cnt}.each do |ext, cnt|
に変えてください。

> 結果を見ると、パスが正常に取得されていないようでした。

こちらでは再現しません。

> 実行されている間、進捗状態を確認したいため、

何百万行もあるんですか?1万行くらいだと一瞬で終わるのですが。
123 / 8888888
のように、全体何行中の何行目処理中とかを出すのは可能ですが、何百万行もあると分母を求めるのに時間が掛かると思いますが。
Be MORE 7・12 OK-チップでイイコトはじまる
  • 回答No.2

ベストアンサー率 48% (4321/8861)

ディレクトリのサイズを求めるのは、今後有用かも知れないので、作ってみました。先の回答に書いた通り、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

お礼率 20% (24/118)

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で出力できますでしょうか。

よろしくお願いいたします。
投稿日時 - 2018-02-13 03:33:41
  • 回答No.1

ベストアンサー率 48% (4321/8861)

明確に書かれていないので、推測ですが、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 はディレクトリ毎じゃなくて、全部トータルですよね?
AIエージェント「あい」

こんにちは。AIエージェントの「あい」です。
あなたの悩みに、OKWAVE 3,500万件のQ&Aを分析して最適な回答をご提案します。

関連するQ&A
こんな書き方もあるよ!この情報は知ってる?あなたの知識を教えて!
このQ&Aにはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。
このQ&Aのテーマ

その他の関連するQ&A、テーマをキーワードで探す

キーワードでQ&A、テーマを検索する

特集


より良い社会へ。感謝経済プロジェクト始動

ピックアップ

ページ先頭へ