Robocopyのログのサマリー部分を整形してみる

Robocopyのログのサマリー部分が見づらいので、整形してみました。

スクリプト名は、logreport.sh です(適当に直して下さい)。

#!/bin/sh

<< COMMENTOUT

2019/09/04作成

robocopyログファイル(Windows2016版)のサマリー部分の整形スクリプト
フォルダ"log"内のrobocopy*.logをUTF-8に変換し、"report"フォルダにサマリー部分を出力します
要 nkf

処理前のlogの最終部分
  ------------------------------------------------------------------------------

                       合計        コピー済み       スキップ       不一致        失敗    Extras
     ディレクトリ:        18571            0      18571         0         0         0
       ファイル:       157425       152728       4697         0         0         0
        バイト: 299399096023 292980525070 6418570953         0         0         0
         時刻:      0:15:20      0:10:48                        0:00:00   0:04:32


         速度:              451855700 バイト/秒
         速度:              25855.390 MB/分
     終了: 2019年xx月xx日 xx:xx:xx

処理後のlog
  ------------------------------------------------------------------------------

                    Total       Copied    Skipped  Mismatch    FAILED    Extras
     Dirs :         18571            0      18571         0         0         0
    Files :        157425       152728       4697         0         0         0
    Bytes :  299399096023 292980525070 6418570953         0         0         0
    Times :       0:15:20      0:10:48                        0:00:00   0:04:32


         速度:              451855700 バイト/秒
         速度:              25855.390 MB/分
     終了: 2019年xx月xx日 xx:xx6:xx

使い方
 カレントディレクトリに"log"というフォルダを作り、robocopyのログファイルを格納します
 カレントディレクトリに"report"というフォルダを作っておきます
 WSLを起動し、カレントディレクトリに移動します
 ./logreport.sh をキックします


※もともとは Powershell で作りましたが、
 処理ファイル数が多いと不安定になるようなので、
 シェルスクリプトで作り直しました

※事前に、WSLにnkfをインストールしておいて下さい

COMMENTOUT

tmpfile=$(mktemp)
tmpfile2=$(mktemp)
tmpfile3=$(mktemp)

# ログファイルの文字コードを UTF-8 にする
cd log
echo ログファイルをUTF-8化しています...
find . -name 'robocopy*.log' -type f -print0 | xargs -0 nkf -u -Lu --overwrite -w 

# ログファイルの最後の15行目を取り出し、
# ----------で始まる行以降を取り出し(ファイルが短くて-----が2行入ってしまった場合は2番目以降)
# サマリー行の全角文字を半角文字に変換する
echo ログファイルを整形出力します
for fname in `find ./robocopy*.log`
do
        echo $fname
        # 各ログファイルの末尾15行を取り出す
        tail -15 $fname > $tmpfile
        if [ `grep -c '^----------' $tmpfile` -eq 2 ] ; then
                # ^---------- が2行ある場合は、最初の行を潰す
                sed '0,/^----------/ s/^----------/xxx/' $tmpfile > $tmpfile3
                # ^---------- 以降を出力
                fname1=${fname#.\/robocopy_}
                echo ${fname1%.log} > $tmpfile2
                sed -n '/^----------/,$p' $tmpfile3 >> $tmpfile2
                rm $tmpfile3
        else
                # ^---------- 以降を出力
                fname1=${fname#.\/robocopy_}
                echo ${fname1%.log} > $tmpfile2
                sed -n '/^----------/,$p' $tmpfile >> $tmpfile2
        fi
        # サマリーの全角を半角に変換
        sed -e 's/^   ディレクトリ:/   Dirs : /g' \
            -e 's/^     ファイル:/  Files : /g' \
            -e 's/^      バイト:/  Bytes : /g' \
            -e 's/^       時刻:/  Times : /g' \
            -e 's/   合計/Total/g' \
            -e 's/ コピー済み/Copied/g' \
            -e 's/   スキップ/Skipped/g' \
            -e 's/     不一致/Mismatch/g' \
            -e 's/    失敗/FAILED/g' \
            $tmpfile2  > ../report/$fname
        done
rm $tmpfile
rm $tmpfile2

以上です。

ROBOCOPYでディレクトリのタイムスタンプが維持できない時

ROBOCOPYのオプションには、ディレクトリに対するコピーフラグがあり、次のような感じになっています。

/DCOPY:コピーフラグ…ディレクトリにコピーする情報 (既定値は /DCOPY:DA)
(コピーフラグ: D= データ、A= 属性、T= タイムスタンプ)

なので、タイムスタンプを維持したいときは、/DCOPY:DTとか、/DCOPY:DATとかやると思います。

しかし、いくつかのOSバージョン(XPから10/2018まで)で試してみたところ、このオプション(フラグT)はWin8.xまたはWin2016以降でないと有効に働かないように見えます(他にも細かい不具合があり、8.1以降/2018以降でやっとまともになった感じです)。

ちなみに、大量のフォルダ/ファイルをコピーするときには、/MTで並列度を上げるよりも、

  • 管理者権限のDOS窓を複数開く
  • スレッド数はある程度抑える(様子を見ながら増減)
  • 各窓でマウントするNETBIOS名は変える(注※)

方が、トータルの速度は上がるようです。

注※(実効コピー速度を上げる方法)

例えば、10.0.0.1という共有サーバを

net use x: \\10.0.0.1\share1 ...
net use y: \\10.0.0.1\share2 ...

という形でマウントし、X:からY:へコピーをするよりも、C:\Windows\System32\drivers\hosts 内で

# 同じCIFS共有ドライブを複数のNETBIOS名で定義する
10.0.0.1   CIFSx
10.0.0.1   CIFSy

とし、

net use x: \\CIFSx\share1 ...
net use y: \\CIFSy\share2 ...
robocopy x: y: ...

とした方が、断然速いです。

このshare1からshare2へのコピーの並列度を上げる場合は、C:\Windows\System32\drivers\hosts 内で

10.0.0.1   CIFSx1
10.0.0.1   CIFSx2
10.0.0.1   CIFSx3
10.0.0.1   CIFSy1
10.0.0.1   CIFSy2
10.0.0.1   CIFSy3

のように定義し、

net use j: \\CIFSx1\share1 ...
net use k: \\CIFSx2\share1 ...
net use l: \\CIFSx3\share1 ...
net use m: \\CIFSy1\share2 ...
net use n: \\CIFSy2\share2 ...
net use o: \\CIFSy3\share2 ...

としてマウントしたあと、管理者権限のDOS窓を開いて

# 窓1で実行
robocopy j:\sub1 m:\sub1 ...
# 窓2で実行
robocopy k:\sub2 n:\sub2 ...
# 窓3で実行
robocopy l:\sub3 o:\sub3 ...

というようにした方が、速いです。

※窓の数や、各窓内の/MT:nの値は、実環境で何パターンかテストして決めて下さい。