Help us understand the problem. What is going on with this article?

WinMergeのコマンドラインオプション

前書き

SIerをディスる記事が登場する度、流れ弾が飛んでくるWinMergeですが、実際のところ、その機能を十分つかいこなせている現場は少ないです。

たとえば、WinMergeはコマンドラインから実行できます。これにより外部プログラムの実行が容易になっているのですが、これはあまり使いこなせていません。
https://manual.winmerge.org/Command_line.html

実はドキュメント化されていないパラメータがいくつかあります。
たとえば、「-or」というレポートを出力するパラメータについては実装はされていますが、ドキュメント化されてはいません。
https://github.com/WinMerge/winmerge/blob/30a5674030a8318a9239893a3cc0a4e8798a6256/Src/MergeCmdLineInfo.cpp

コマンドラインのパラメータ

2.16.4.0でサポートしているパラメータは下記のようになります。
これは下記を参考に作成しています。
・ヘルプ
https://github.com/WinMerge/winmerge/blob/30a5674030a8318a9239893a3cc0a4e8798a6256/Src/MergeCmdLineInfo.cpp
https://sourceforge.net/p/winmerge/support-requests/109/

オプション 説明
-? WinMergeヘルプを開きます
-o "outputfilename" マージした結果のファイルを保存するオプションの出力フォルダを指定します。 もし、出力パスを指定した場合、あるペインを変更後保存すると、変更は出力パスのファイルに保存され、 元ファイルは前の状態のままになります。
-or "reportfilename" レポートの出力を出力するパスを指定します。この機能はドキュメントにのっていません。
dl "desc" 左側タイトルバーの説明を指定します。 デフォルトのフォルダやファイル名テキストに上書きされます。例: /dl "Version 1.0" や /dl WorkingCopy. スペースを含む説明はダブルクォーテーションマークで括ってください。
-dm "desc" /dlと同様に中央タイトルバーの説明を指定します。
-dr "desc" /dlと同様に右側タイトルバーの説明を指定します。
-e EscキーでWinMergeが閉じるようにします。 WinMergeを外部比較アプリケーションとして使用する場合に便利です。 (ダイアログのようにすばやくWinMergeを閉じることができます) この引数を指定しなかった場合、すべてのウインドウを閉じるのに何回もEscキーを 押さなければならないことになるかもしれません。(2つ以上タブが開かれている場合、一回のESCキーの押下でWinMergeが終了してしまうのを期待している人はいないような気がしたので、日本語版ではこのオプションを指定しても2つ以上タブが開かれている場合は1つのタブを閉じるだけにし、タブが1つの時またはタブが一つもない時にWinMergeを終了するようにしました)
-f "mask" 比較を制限するために、指定したフィルタを適用します。 フィルタは*.h *.cppのようなファイルマスクか、 XML/HTML Develのようなファイルフィルタの名前です。 スペースを含むフィルタマスクやフィルタ名はダブルクォーテーションマークで括ってください
-r すべてのサブフォルダ内のすべてのファイルを比較します(再帰比較)。 ユニークフォルダ (片方のみ存在するフォルダ)は、分離された項目として比較結果内にリストされます。 サブフォルダまで含めるとかなり比較時間が増大してしまうことに注意してください。 このパラメータを指定しなかった場合、WinMergeは比較するフォルダ内のファイルとトップレベルのサブフォルダのみリストします。 サブフォルダの中までは比較しません。
-s WinMergeウインドウを1つのインスタンスに制限します。 例えば、WinMergeが既に実行中ならば、新しい比較は同じインスタンス内で実行されます。 この引数を指定しなかった場合、複数のウインドウが開かれる可能性があります: 設定によっては、新しい比較が既に存在するウインドウで実行されることも新しいウインドウで 実行されることもあります。
-noninteractive 比較やレポート出力後にWinMergeを終了します。この機能はドキュメントにのっていません。
-noprefs レジストリの読み書きをしません。設定値はデフォルトを使用します。この機能はドキュメントにのっていません。
-minimize minimize 最小化状態でWinMergeを開始します。 このオプションは長時間かかる比較を行う場合に便利です。
-maximize 最大化状態でWinMergeを開始します。
-prediffer predifferプラグイン 指定されている場合はpredifferプラグインを取得します(それ以外の場合、predifferプラグインは空白になります。これはデフォルトです)。この機能はドキュメントにのっていません。
-wl 読み取り専用として左側を開きます。 比較時、左側を変更したくない場合に使用してください。
-wm 読み取り専用として中央を開きます。 比較時、中央を変更したくない場合に使用してください。
-wr 読み取り専用として右側を開きます。 比較時、右側を変更したくない場合に使用してください
-ul 左側パスが最近使用した項目(MRU)リストに追加されるのを防ぎます。 外部アプリケーションは、ファイルまたはフォルダの選択ダイアログのMRUリストにパスを 追加するべきではありません
-um 中央のパスが最近使用した項目(MRU)リストに追加されるのを防ぎます。 外部アプリケーションは、ファイルまたはフォルダの選択ダイアログのMRUリストにパスを 追加するべきではありません。
-ur 右側パスが最近使用した項目(MRU)リストに追加されるのを防ぎます。 外部アプリケーションは、ファイルまたはフォルダの選択ダイアログのMRUリストにパスを 追加するべきではありません。
-u または -ub(非推奨) /u (または/ub) 各々(左、右、中央)のパスが最近使用した項目(MRU)リストに追加されるのを防ぎます。 外部アプリケーションは、ファイルまたはフォルダの選択ダイアログのMRUリストにパスを 追加するべきではありません。
-fl 起動時、左側にフォーカスを当てます
-fm 起動時、中央にフォーカスを当てます
-fr 起動時、右側にフォーカスを当てます
-al 起動時、左側で自動マージします。
-am 起動時、中央で自動マージします。
-ar 起動時、右側で自動マージします。
-x 同一ファイルの比較をしたときにWinMergeを閉じます。 (情報ダイアログを表示した後) このパラメータは比較後に効果がなくなります。 例えば、もしファイルがマージか編集の結果として同一となった場合です。 このパラメータは、WinMergeを外部アプリケーションとして使用したり、 差異のないファイルを無視することによって余分なステップを取り除きたい場合に便利です。
-xq -x に似ていますが、同一ファイルであってもメッセージボックスを表示しません
-cp コードページ 比較時のコードページを指定します。この機能はドキュメントにのっていません。
-ignorews 空白を無視します。この機能はドキュメントにのっていません。
-ignoreblanklines 空白行を無視します。この機能はドキュメントにのっていません。
-ignorecase 大文字小文字を無視します。この機能はドキュメントにのっていません。
-ignoreeol 改行の無視します。この機能はドキュメントにのっていません。
-ignorecodepage コードページの違いを無視します。この機能はドキュメントにのっていません。
-cfg 設定情報または-config 設定情報 設定情報をコマンドラインから指定します。この機能はドキュメントにのっていません。詳細は[設定情報をコマンドラインで渡す])#設定情報をコマンドラインで渡す)を参照してください

設定情報をコマンドラインで渡す

以下のような記載で設定情報をコマンドラインから渡すことが可能です。

"C:\Program Files\WinMerge\WinMergeU.exe" C:\dev\winmerge\a.txt C:\dev\winmerge\b.txt -cfg "Font/Height=32" -cfg "Font/FaceName=MS 明朝" -cfg "Font/Underline=1"

image.png

-cfgで指定できる設定項目の種類は設定値からエクスポートしたものと同じになります。

・編集→設定でひらくオプション画面で「エクスポート」を行う
image.png

・作成されるINIファイルは下記の通り
image.png

ファイルの比較結果をレポートとして出力する例

/orを使用してレポートにファイルを出力します。
この際、同時に/noninteractiveを指定してレポート出力後にWinMergeを終了します。

"C:\Program Files\WinMerge\WinMergeU.exe" C:\dev\winmerge\test1.txt C:\dev\winmerge\test2.txt  /minimize /noninteractive /u /or C:\dev\winmerge\out.html

作成されたレポート
image.png

フォルダの比較結果をレポートとして出力する例

-orを使用してレポートにファイルを出力します。
-noninteractiveを指定してレポート出力後にWinMergeを終了します。
-rを使用してサブフォルダを含めて比較を行います。
-cfgを指定して下記の設定を適用します。
 Settings/DirViewExpandSubdirs=1 …オプションの比較>フォルダー>自動的にサブフォルダーを展開する
 ReportFiles/ReportType=2 …フォルダ比較レポート>スタイル:シンプルなHTML形式
 ReportFiles/IncludeFileCmpReport=1 …フォルダ比較レポート>ファイル比較レポートを含める

"C:\Program Files\WinMerge\WinMergeU.exe" C:\dev\winmerge\abc C:\dev\winmerge\acc -minimize -noninteractive -noprefs -cfg Settings/DirViewExpandSubdirs=1 -cfg ReportFiles/ReportType=2 -cfg ReportFiles/IncludeFileCmpReport=1 -r -u -or C:\dev\winmerge\out2.html

作成されたレポート(ディレクトリの比較結果)
image.png

※注意:2.14だと-minimizeがついているとレポートが常に差分なしになってしまう。

コマンドラインからマージする例

"C:\Program Files\WinMerge\WinMergeU.exe" base.c remote.c local.c /ar /u /o C:\dev\winmerge\out.c /noninteractive

残念ながら、以下で止まるのでコマンドラインだけの操作で自動化はできません。
またコンフリクトが発生した場合も、マージできません。

image.png

どうしても自動化したかったら以下のPowerShellを使います。

automerge.ps1
Add-Type -AssemblyName UIAutomationClient
Add-Type -AssemblyName UIAutomationTypes
Add-type -AssemblyName System.Windows.Forms

$source = @"
using System;
using System.Windows.Automation;
public class AutomationHelper
{
    public static AutomationElement RootElement
    {
        get
        {
            return AutomationElement.RootElement;
        }
    }

    public static AutomationElement GetWindowByTitle(string title) {
        var rootCond = new PropertyCondition(AutomationElement.ClassNameProperty, "WinMergeWindowClassW");
        var cond = new PropertyCondition(AutomationElement.NameProperty, title);
        var elementCollection = RootElement.FindAll(TreeScope.Children, rootCond);
        foreach(AutomationElement mainForm in elementCollection) {
            var win =  mainForm.FindFirst(TreeScope.Children, cond);
            if (win != null) {
                return win;
            }
        }
        return null;
    }

    public static AutomationElement WaitWindowByTitle(string title, int timeout = 10) {
        DateTime start = DateTime.Now;
        while (true) {
            AutomationElement ret = GetWindowByTitle(title);
            if (ret != null) {
                return ret;
            }
            TimeSpan ts = DateTime.Now - start;
            if (ts.TotalSeconds > timeout) {
               return null;
            }
            System.Threading.Thread.Sleep(100);
        }
    }

}
"@
Add-Type -TypeDefinition $source -ReferencedAssemblies("UIAutomationClient", "UIAutomationTypes")

# 5.0以降ならusingで記載した方が楽。
$autoElem = [System.Windows.Automation.AutomationElement]

# ウィンドウ以下で指定の条件に当てはまるコントロールを1つ取得
function findFirstElement($form, $condProp, $condValue) {
    $cond = New-Object -TypeName System.Windows.Automation.PropertyCondition($condProp, $condValue)
    return $form.FindFirst([System.Windows.Automation.TreeScope]::Element -bor [System.Windows.Automation.TreeScope]::Descendants, $cond)
}

# 指定のAutomationIDのボタンを押下
function pushButtonById($form, $id) {
    $buttonElem = findFirstElement $form $autoElem::AutomationIdProperty $id
    $invElm = $buttonElem.GetCurrentPattern([System.Windows.Automation.InvokePattern]::Pattern) -as [System.Windows.Automation.InvokePattern]
    $invElm.Invoke()
}


# 5秒間ダイアログがでるのを待機しているが、あまりよくない。
$dialog = [AutomationHelper]::WaitWindowByTitle("変更されたファイルを保存しますか?", 5)
if ($dialog -eq $null) {
    Write-Host "マージできませんでした"
} else {
    pushButtonById $dialog "1"
    Write-Host "マージでしました"
}


このPowerShellを以下のような感じで実行します。

start cmd /c "C:\Program Files\WinMerge\WinMergeU.exe" base.c remote.c local.c /ar /u /o C:\dev\winmerge\out.c /noninteractive
powershell -ExecutionPolicy RemoteSigned -File  ./automerge.ps1

タイトルバーの説明 /dl /dm /dr

/dl /dm /drはタイトルバーに説明を追加します。

WinMergeU.exe C:\dev\winmerge\test1.txt C:\dev\winmerge\test2.txt C:\dev\winmerge\test3.txt /dl "Version 1.0" /dm "Version 1.1" /dr "Version 1.2"

image.png

ファイルフィルタの設定 /f

指定したフィルタを設定して比較対象のファイルを制限します。
スペースで区切ることで複数のファイルを指定することが可能です。

以下の例ではcppとhのみをフィルタした結果となります。

WinMergeU.exe C:\dev\winmerge\abc C:\dev\winmerge\acc -f "*.cpp *.h"

image.png
※他の拡張子が表示されない

末尾の空白の無視 /ignorews

末尾の半角スペースとタブを無視します。

空白を無視しない場合:
image.png

空白を無視する場合:

"C:\Program Files\WinMerge\WinMergeU.exe" C:\dev\winmerge\a.txt C:\dev\winmerge\b.txt  /ignorews

image.png

空白行の無視 /ignoreblanklines

ignoreblanklinesオプションを使用することで空白行の差異を無視することができます。

空白行を無視しない
image.png

空白行を無視する

"C:\Program Files\WinMerge\WinMergeU.exe" C:\dev\winmerge\a.txt C:\dev\winmerge\b.txt  /ignoreblanklines

image.png

大文字小文字を無視 /ignorecase

ignorecaseオプションを利用することで大文字小文字の差異を無視することが可能です。

無視しない場合
image.png

無視する場合

"C:\Program Files\WinMerge\WinMergeU.exe" C:\dev\winmerge\c.txt C:\dev\winmerge\d.txt   /ignorecase

image.png

改行文字の無視 /ignoreeol

行末の改行文字の違いを無視します。

無視しない場合
image.png

無視する場合

"C:\Program Files\WinMerge\WinMergeU.exe" C:\dev\winmerge\a.txt C:\dev\winmerge\b.txt  /ignoreeol

image.png

コードページの無視 /ignorecodepage

/ignorecodepageでコードページの差異を無視できます。
ただし、2.16.4.0で実験した限り、このパラメータを無効にしてかつ、下記の設定であっても、コードページの違いを無視して比較しているようです。

image.png

image.png
※コードページの違いを無視する設定で、文字コードのことなるファイルを比較しても差異がでてこない。

まとめ

コマンドラインを利用することで自動でレポートの作成が行えます。
ただし、パッチの作成や、マージ結果の作成は自動でできないようです。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away