あるディレクトリにaaa_2006MMDYHH.binのバイナリファイルが複数あるとします.
MMは月(01,02,...12),DYは日(01,02, ...,[月末日]),HH(00, 01, ..., 23)は時間を表しており,各ファイルのサイズは同じです.
ここで,ファイルが1時間置きに全ての日数分存在しているかどうか,さらにそのなかで破損ファイル(ファイル自体は存在するがファイルサイズがほかと異なる)が存在するかどうかを自動でチェックしたいのですが,何かよい方法はありますか?現在シェルかpythonで組もうとしているのですが各ファイルのファイルサイズを取得する部分でつまづいてます.
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答6件
0
ベストアンサー
大の月/小の月などを一々条件判定するのはダサイと思い、datetimeにやらせてみることにしました。
Python
1import os.path 2import datetime as dt 3 4dt0 = dt.datetime(2016,1,31,0,0,0) 5dt1 = dt.datetime(2016,12,31,23,0,0) 6filesize = os.path.getsize("aaa_2006010101.bin") 7 8while True: 9 if dt0==dt1: 10 break 11 filename = "aaa_{y:4d}{m:02d}{d:02d}{h:02d}.bin".format(y=dt0.year, m=dt0.month, d=dt0.day, h=dt0.hour) 12 if os.path.exists(filename): 13 if os.path.getsize(filename)!=filesize: 14 print(filename + " looks broken.") 15 else: 16 print(filename + " looks ok.") 17 else: 18 print(filename + " does not exist.") 19 dt0 = dt0 + dt.timedelta(hours=1)
投稿2018/03/08 17:27
総合スコア13671
0
質問文で一番気になるポイントはファイル書き出し側の処理がos.rename windowsならos.replaceを使ってアトミックにファイルを書き出しているかどうかですが。。。
2案あります。
案1,ファイルサイズでソートしてチェック
ファイルの漏れはファイル数でチェック。
案2,ファイルの日付を生成してループで回してチェック
案2のファイルサイズのチェックまでのコードのサンプルです。
Python
1# -*- coding: utf-8 -*- 2from pathlib import Path 3from datetime import datetime, timedelta 4from collections import Counter 5 6def date_generator(): 7 # 年,月,日,時間 8 current_date = datetime(2006, 1, 1, 0) 9 end_date = datetime(2006, 1, 1, 3) 10 #end_date = datetime(2007, 1, 1, 0) 11 while True: 12 yield current_date 13 current_date += timedelta(hours=1) 14 if current_date == end_date: 15 break 16 17 18def main() -> None: 19 not_founds = [] 20 file_sizes = Counter() 21 for dt in date_generator(): 22 file_name = f"aaa_{dt.strftime('%Y%m%d%H')}.bin" 23 p = Path(file_name) 24 try: 25 st_size = p.stat().st_size 26 file_sizes[st_size] = str(p) 27 except FileNotFoundError as ex: 28 not_founds.append(str(p)) 29 pass 30 # ファイルが存在しない物 31 if len(not_founds) >0: 32 print(not_founds) 33 34 print(file_sizes.most_common(5)) 35 36 37if __name__ == "__main__": 38 main() 39
Note:os.scandirを使う事も検討してみてくださいな。
投稿2018/03/08 17:23
編集2018/03/08 18:00総合スコア5846
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
抜けファイルのチェック(bash 4.x以上)
bash
1$ echo 2006{{01,03,05,07,08,10,12}{01..31},{04,06,09,11}{01..30},02{01..28}}|xargs -n1 -I@ echo "echo aaa_@{00..23}.bin"|sort|sh|xargs ls >/dev/null
投稿2018/03/08 14:25
編集2018/03/08 14:26総合スコア5737
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
ファイルのサイズを表示するPythonのプログラム:
# os.pathというモジュールのgetsize関数を使うので、最初にインポートしておく import os.path filepath = サイズを調べたいファイルのパス #getsize関数でファイルのサイズを調べて、それを表示 print os.path.getsize(filepath)
こんな感じでファイルのサイズを取得できます。
1年分のバイナリファイルがあるかどうかは、だいたい以下のような感じ(実行、デバッグをしていないコードなので、雰囲気をとらえるのに使ってください)
days = [31,28,31,30,31,30,31,31,30,31,30,31] #各月の日数のリスト。 1月は31日、2月は28日、、、を表したものを用意しておく folderpath = ファイルが置かれているディレクトリのパスを設定 normalfilesize = ファイルの正しいサイズを設定 flag=True #バイナリファイルがちゃんと揃っている事を示すフラグを初期化 For mm in range(12) #月のループ for dy in range(days[mm]) # 日のループ。リストdaysを使うことで月の日数が変化することに対応 for hh in range(24) # 時間のループ #月、日、時間の値から、ファイルパスの文字を作る #rangeを使っているのでmmは0から11まで変わるから、+1して1(月)から12(月)になるようにする。dy,hhも同様 filepath = folderpath + "/" + "aaa_2006" + (mm+1) + (dy+1) + (hh+1) + ".bin" if os.path.exists(filepath): #ファイルが存在する場合 if os.path.getsize(filepath) == normalfilesize: #ファイルサイズが正しい場合 else: ファイルサイズが正しくない場合 flag=False #バイナリファイルのサイズが正しくない # ここにファイルサイズが正しくない場合の処理(エラー処理)を書く else: #ファイルが存在しない場合 flag=False #バイナリファイルがちゃんと揃っていない(欠落がある) # ここにファイルが存在しない場合の処理(エラー処理)を書く if flag: #バイナリファイルがちゃんと揃っていた時の処理を書く (print "OK" とか) else: #バイナリファイルがちゃんと揃っていた時の処理を書く (print "NG" とか)
投稿2018/03/08 13:21
総合スコア6915
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
とりあえずファイルサイズについて。
ls -l aaa_*.bin| awk '{print $5}'
ぐらいで各ファイルのバイト数の一覧が取れます。そう考えると全ての対象ファイルで同じサイズになっているなら
ls -l aaa_*.bin | awk '{print $5}' | uniq
は結果が1行になるでしょうから
ls -l aaa_*.bin | awk '{print $5}' | uniq | wc | awk '{print $1}'
が1かどうかで判定できるのではないでしょうか。自分はawkを使う癖があるのですが、もっと別の(よりシンプルな)書き方もあると思います。
aaa_*.binというパターンは適当です。必要ならもっと厳密に指定すればよいと思います。
投稿2018/03/08 12:46
総合スコア18394
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/10 06:43