ラベル Windowsバッチファイル の投稿を表示しています。 すべての投稿を表示
ラベル Windowsバッチファイル の投稿を表示しています。 すべての投稿を表示
2015年6月7日日曜日

robocopyを使ったハードディスクのバックアップスクリプト

以前Buffalo製のNASを使っており、そんなに安くもない値段がしたNASだったが、1年ちょっとで起動しなくなった。そのNASはUSBを繋げばバックアップを取得できる仕様だったのでデータロストはしなかったが、BuffaloのNASは二度と使わないと心に決めた瞬間だった(といいながら、現状はBuffalo製のUSBハードディスクにデータを保存している)。

データロストを恐れて、さらにもう1つUSBハードディスクを買って、気が向いたら手動でUSBハードディスク間のコピーを実施する運用にしているが、その際に、手作業でコピーするのは面倒なので、Windows標準で使えるrobocopyコマンドを使ってスクリプトを作っておくことにした。

スクリプト内容

先にスクリプトの中身を見せてしまうと、以下のようになる。極めてシンプルだが、差分コピーでコピー元(SRC)とコピー先(DST)をミラーリングできるスグレモノ。タイムスタンプもディレクトリ含めてきちんと一致してコピーされる。

-------------------ここから
@echo off
set SRC=d:\
set DST=z:\

echo %SRC%→%DST%のミラーリングを開始します。
pause

set TODAY=%DATE:/=%
robocopy %SRC% %DST% /MIR /DCOPY:T /R:1 /W:5 /XD "System Volume Information" "$RECYCLE.BIN" > d:\copy_%TODAY%.log

echo %SRC%→%DST%のミラーリングが終了しました。
pause

exit 0
-------------------ここまで

スクリプトのログ

これを実行すると、以下のようなログが出力される(以下ログは表示用に少し整形済み)。2回目以降は差分コピーなので、変更が少なければかなり短い時間でコピーは終わる。

ログの最後には、結果のサマリが表示され、ファイル数・スキップ数(同一ファイルが存在)・失敗数(何らかの理由でコピー失敗)などが確認できる。

-------------------ここから

------------------------------------------------------------
   ROBOCOPY     ::     Windows の堅牢性の高いファイル コピー                            
------------------------------------------------------------

  開始: Sun Jun 07 17:31:36 2015

   コピー元 : d:\
     コピー先 : z:\

    ファイル: *.*
 
 除外ディレクトリ: System Volume Information
   $RECYCLE.BIN
 
  オプション: *.* /S /E /COPY:DAT /DCOPY:T /PURGE /MIR /R:1 /W:5

------------------------------------------------------------

                   3 d:\
    新しいファイル   338   copy - コピー.bat  0%  100%
    より新しい         299   copy.bat              0%  100%
    より新しい            0   copy_20150607.log 0%  100%

               … (中略) …

                   2 d:\temp\

------------------------------------------------------------

                  合計     コピー済み      スキップ       不一致        失敗    Extras
   ディレクトリ:      3198         0      3198         0         0         0
     ファイル:     83816         3     83813         0         0         0
      バイト: 532.962 g       637 532.962 g         0         0         0
       時刻:   0:00:03   0:00:01                       0:00:00   0:00:02


       速度:                 619 バイト/秒
       速度:               0.035 MB/分

       終了: Sun Jun 07 17:31:39 2015

-------------------ここまで

robocopyの説明

robocopyコマンドはオプションが多数存在するが、今回使用しているコマンドのオプションについて簡単に説明する。

◆コマンド
robocopy %SRC% %DST% /MIR /DCOPY:T /R:1 /W:5 /XD "System Volume Information" "$RECYCLE.BIN" > d:\copy_%TODAY%.log

◆使用オプション
/MIR : MIRRORの意味。全てのファイルのコピーと削除を行いディスクの内容を同一にする
/DCOPY:T : ディレクトリのタイムスタンプのコピー
/R:1 : Retry回数。省略すると100万回繰り返すので必ず指定することを推奨
/W:5 : リトライ時にWaitする時間。省略すると30秒
/XD : eXclude Directoryの略と思われる。コピー除外フォルダを指定する。

参考URL

Robocopy
https://technet.microsoft.com/ja-jp/library/cc733145%28v=ws.10%29.aspx

2015年2月1日日曜日

Windows標準コマンドでgrepする

前回の「Windows標準コマンドでdiffする」に引き続き、今回はgrep。

コマンドプロンプト

findstrというコマンドが用意されている。ヘルプを見てみる。
c:\>findstr /?
ファイルから文字列を検索します。

FINDSTR [/B] [/E] [/L] [/R] [/S] [/I] [/X] [/V] [/N] [/M] [/O] [/P]
        [/F:ファイル] [/C:文字列] [/G:ファイル] [/D:ディレクトリ一覧]
        [/A:色属性] [/OFF[LINE]] 文字列 [[ドライブ:][パス]ファイル名[ ...]]
  /B           行の先頭にあるパターンを検索します。
  /E           行の末尾にあるパターンを検索します。
  /L           検索文字列をリテラルとして使用します。
  /R           検索文字列を正規表現として使用します。
  /S           現在のディレクトリとすべてのサブディレクトリから一致する
               ファイルを検索します。
  /I           検索するときに大文字と小文字を区別しません。
  /X           完全に一致する行を出力します。
  /V           一致しない行のみを出力します。
  /N           一致する各行の前に行番号を出力します。
  /M           ファイルに一致する行があるときに、ファイル名のみを出力します。
  /O           一致する各行の前に文字オフセットを出力します。
  /P           印刷不可能な文字を含むファイルをスキップします。
  /OFF[LINE]   オフライン属性が設定されたファイルをスキップしません。
  /A:属性      2 桁の 16 進数で色属性を指定します。"color /?" を参照してくだ
               さい。
  /F:ファイル  指定したファイルからファイル一覧を読み取ります (/ を指定するとコンソール)。
  /C:文字列    指定された文字列をリテラル検索文字列として使用します。
  /G:ファイル  指定されたファイルから検索文字列を取得します (/ を指定するとコンソール)。
  /D:ディレクトリ
               セミコロンで区切られた検索されるディレクトリ文字列テキストの一覧を検索します。
  [ドライブ:][パス]ファイル名
               検索するファイルを指定します。

複数の文字列を検索する場合には、引数 /C を使わず、各文字列をスペースで区切ります。
たとえば、FINDSTR "hello there" x.y と指定した場合は、ファイル x.y で "hello"または "there" が検索されます。
これに対して、FINDSTR /C:"hello there" x.y と指定した場合はファイル x.y で"hello there" が検索されます。

正規表現クイック リファレンス:
  .            ワイルドカード: 任意の文字
  *            繰り返し: ゼロ個以上の直前の文字またはクラス
  ^            行位置: 行頭
  $            行位置: 行末
  [class]      文字クラス: セットの任意の 1 文字
  [^class]     逆クラス: セット以外の任意の 1 文字
  [x-y]        範囲: 指定した範囲の任意の文字
  \x           エスケープ: メタ文字 x のリテラル使用
  \<xyz        単語位置: 単語の先頭
  xyz\>        単語位置: 単語の終わり

FINDSTR の詳細な正規表現に関しては、オンライン ヘルプのコマンド リファレンスを参照してください。
正規表現も使えて中々便利そう。/xで完全一致、/nで抽出行番号、/rで正規表現利用を選択すると使いやすそう。オプション無しでも普通に正規表現使えるっぽいが。
※test.txtの中身は以下3行
hoge
hogehoge
hoge3

C:\>findstr /xnr "^ho.*ho.*" test.txt
2:hogehoge
さらにファイル名にワイルドカードを使って複数ファイルのgrepも可能になっていて、意外と高機能。
C:\>findstr /xnr "^ho.*ho.*" test*.txt
test.txt:2:hogehoge
test2.txt:2:hogehoge

PowerShell

Select-Stringというコマンドレットがあるのでそれを使う。ファイル名にワイルドカードを使って複数ファイルのgrepも可能。
PS C:\> Select-String "^ho.*ho" .\test.txt

test.txt:2:hogehoge

2015年1月31日土曜日

Windows標準コマンドでdiffする


Linuxなら迷うこと無くdiffコマンドがあるので問題ないが、Windowsの場合どうすれば良いか悩んでしまうことがある。フリーソフトがインストールできる環境ならまだしも、インターネットに繋がないサーバーとなると、OS標準のコマンドで実施する必要があるので調べてみた。

Windowsバッチファイル

実はコマンドがあってfc (File Compare) を使えば良い。オプションを確認してみよう。
C:\>fc /?
2 つのファイルまたはファイル セットを比較し、相違点を表示します。


FC [/A] [/C] [/L] [/LBn] [/N] [/OFF[LINE]] [/T] [/U] [/W] [/nnnn]
   [ドライブ1:][パス1]ファイル名1 [ドライブ2:][パス2]ファイル名2
FC /B [ドライブ1:][パス1]ファイル名1 [ドライブ2:][パス2]ファイル名2

  /A         相違する各部分の 1 行目と最後の行だけを表示します。
  /B         バイナリの比較を実行します。
  /C         英字の大文字と小文字を区別しません。
  /L         ファイルを ASCII テキストとして比較します。
  /LBn       連続する最大不一致行を指定行数に設定します。
  /N         ASCII の比較で行番号を表示します。
  /OFF[LINE] オフライン属性が設定されたファイルをスキップしません。
  /T         タブをスペースに変換しません。
  /U         Unicode テキスト ファイルとしてファイルを比較します。
  /W         連続した空白 (タブとスペース) を 1 つのスペースに圧縮して比較
             します。
  /nnnn      不一致発見後に確認する、一致すべき連続行数を指定します。

  [ドライブ1:][パス1]ファイル名1
             比較する最初のファイルまたはファイル セットを指定します。
  [ドライブ2:][パス2]ファイル名2
             比較する 2 番目のファイルまたはファイル セットを指定します。
見ての通りいろいろオプションはあるが、お勧めは/n付けて相違行番号を出すと比較結果が確認しやすい。
(実行例)
c:\>fc /n test.txt test2.txt
ファイル test.txt と TEST2.TXT を比較しています
***** test.txt
***** TEST2.TXT
    5:
    6:  hoge4
*****

PowerShell

Compare-Objectを使う。さらに標準でdiffcompareでエイリアスに登録されているので、以下コマンドで実行することができる。

PowerShell的にはあくまでオブジェクトの比較になるので、一度cat(Get-Contentのエイリアス) でテキストを読み込ませてから比較する必要がある。SideIndicator=>となっていれば引数の右側、<=になっていれば引数の左側に差異があることを表している。
PS C:\> diff (cat '.\test.txt') (cat .\test2.txt)
 
InputObject                                                 SideIndicator
-----------                                                 -------------
                                                            =>
hoge4                                                       =>

2015年1月28日水曜日

バッチファイルの遅延環境変数の展開

バッチファイルの遅延環境変数の展開について知らなかったため、先日バッチファイル作成時にハマってしまった。調べればもっとわかりやすいサイトもあるが、自分でもスクリプト作って調査・確認をしたので備忘として残しておく。

環境変数の展開というバッチファイルの罠

バッチファイルは1行1行読み込みながらコマンドを解釈して処理を実行する。変数がある場合は、1行読み込んだ際に値を代入して処理をする。しかし、if文やfor文の場合は、if文の中身も含めて一気に変数に値を代入する(環境変数が展開される)という、バッチファイルならではの癖がある。

例を出そう。以下は1~10までを足し算するバッチファイルである。
rem 1~10までを足し算する
@echo off
set i=0
for /l %%X in (1,1,10) do (
set /a i=%i% + %%X
echo %i%
)
echo %i%
pause
exit 0
結果は55が最後に表示されることを期待するが、以下の通りうまくいかない。
0
0
0
0
0
0
0
0
0
0
10
続行するには何かキーを押してください . . .
なぜかというとfor文の()の中身は、for文開始時に変数iが0で展開されてしまうから。わかりやすく書くと、以下を実行していることと同一になってしまう(ループの最後は%%Xは10が入るので、それが変数iに代入されて終わる)。
rem 1~10までを足し算する
@echo off
set i=0
for /l %%X in (1,1,10) do (
set /a i=0 + %%X
echo 0
)
echo %i%
pause
exit 0

遅延環境変数の展開を有効化する

問題を解決するためには、以下2点を対応すれば良い。

  1. 最初に"setlocal enabledelayedexpansion"を書いて、遅延環境変数の展開を有効化
  2. 遅延環境変数は"%"ではなく"!"で囲む

試してみよう。
rem 1~10までを足し算する
@echo off
rem 遅延環境変数
setlocal enabledelayedexpansion

set i=0
for /l %%X in (1,1,10) do (
set /a i=!i! + %%X
echo !i!
)
echo %i%
pause
exit 0

結果。
1
3
6
10
15
21
28
36
45
55
55
続行するには何かキーを押してください . . .
以上の通り、想定される55の結果が表示された。

2015年1月15日木曜日

いろんなスクリプトでYYYYMMDDの日付の文字列を作る方法

本日日付のディレクトリを作成したり、バックアップファイルのファイル名の末尾に日付を付けたりする際に、20150115のように、本日の日付からYYYYMMDDの文字列を作りたくなることが多い。

各スクリプト言語でやり方は決まっているので、まとめておく。

Windowsバッチファイル

その①
set TODAY=%DATE:/=%
その②
for /f usebackq %%l in (`echo %date:~-10,4%%date:~-5,2%%date:~-2,2%`) do set TODAY=%%l

PowerShell

$today = Get-Date -Format "yyyyMMdd"

Linuxシェルスクリプト

_today=`date +"%Y%m%d"`

Excel数式

=TEXT(TODAY(),"yyyymmdd")

Excel VBA

Cells(1, 1) = Format(Date, "yyyymmdd")


2015年1月6日火曜日

Windowsパッチ一括適用バッチファイル

インターネットやWSUSがある環境であれば苦労しないが、社内システムでWSUSも無い環境の場合はWindowsパッチ適用を月1回手動で当てるといった対応を強いられる場合がある。1個や2個当てる分には耐えられるが、これが10個とか当てる場合、気が遠くなるような作業になる(大げさかもしれないが少なくとも効率は悪い)。

というわけで、超簡単なパッチ一括適用バッチファイルを作ってみた。パッチをpatchするbatということで、patch_patch.batと名付けた。

patch_patch.bat

以下をバッチファイルとして保存し、msuファイルと同一フォルダに置いて管理者として実行すればOK。最後に再起動を忘れないように。

---------------------
@echo off
rem 使い方:*.msuファイルと同じフォルダにて本バッチを実行

rem 開始確認
set /p YORN="パッチ適用を開始します。 (y or n):"
if not '%YORN%'=='y' (
   echo "処理を中止"
   GOTO END
)

rem 適用
for /r %%i in (*.msu) do (
    echo C:\Windows\System32\WUSA.EXE %%i /quiet /norestart
    C:\Windows\System32\WUSA.EXE %%i /quiet /norestart
)

:END

pause
---------------------

人気の投稿