本日も乙

ただの自己満足な備忘録。

Mercurialのinclude,excludeのpattern(glob)について

小ネタです。 仕事でバージョン管理にMercurialを使っています。バージョン管理(リポジトリに登録)されているファイル一覧を取得したい場合に「hg locate」コマンドを使うのですが、パターンを絞ってファイル一覧を取得したかったので、include,excludeオプションについて調べたことを書き留めておきます。

hg locate とは

ヘルプを見ると、Mercurialで管理されているファイル郡で特定パターンに一致するファイルを探すコマンドと書いてあります。

$ hg locate --help

hg locate [OPTION]... [PATTERN]...

locate files matching specific patterns

    Print files under Mercurial control in the working directory whose names
    match the given patterns.

    By default, this command searches all directories in the working
    directory. To search just the current directory and its subdirectories,
    use "--include .".

    If no patterns are given to match, this command prints the names of all
    files under Mercurial control in the working directory.

    If you want to feed the output of this command into the "xargs" command,
    use the -0 option to both this command and "xargs". This will avoid the
    problem of "xargs" treating single filenames that contain whitespace as
    multiple filenames.

    Returns 0 if a match is found, 1 otherwise.

options:

 -r --rev REV             search the repository as it is in REV
 -0 --print0              end filenames with NUL, for use with xargs
 -f --fullpath            print complete paths from the filesystem root
 -I --include PATTERN [+] include names matching the given patterns
 -X --exclude PATTERN [+] exclude names matching the given patterns
    --mq                  operate on patch repository

[+] marked option can be specified multiple times

use "hg -v help locate" to show the global options

デフォルトでは(Mercurial管理範囲内の)ディレクトリ内全てのファイルを探すのですが、includeオプションやexcludeオプションを使うことでパターンを絞ったり除外することができます。

[plain] --include (-I) ・・・ パターンにマッチしたものだけを含める --exclude (-X) ・・・ パターンにマッチしたものを除外 [/plain]

サンプルファイル

これらのオプションを理解するために以下のようなサンプルファイルを作成してみます。 ファイル作成時にすでにリポジトリに登録しているものとします。

$ tree hg_hoge
hg_hoge
├── .hg
├── 1.html
├── 1.php
├── 2.html
├── 2.php
├── 3.html
├── 3.php
├── 7.txt
└── fuga
    ├── 11.html
    ├── 12.php
    └── 13.js

まず通常の hg locate

当然のことながらリポジトリに登録されているファイルすべてが表示されます。

$ cd hg_hoge
$ hg locate
1.html
1.php
2.html
2.php
3.html
3.php
7.txt
fuga/11.html
fuga/12.php
fuga/13.js

includeオプションを使う

まず、「.html」を含むファイルのみを表示させます。

$ hg locate --include 'glob:*.html'
1.html
2.html
3.html

$ hg locate --include 'glob:**.html'
1.html
2.html
3.html
fuga/11.html

2つのコマンドの違いが分かりますでしょうか。 1つ目のパターンが「'glob:*.html'」で、2つ目のパターンが「'glob:**.html'」で「*」が1つだけ異なります。 1つ目のパターンでは、「*」が任意の文字列(文字数関係なし)に合致させるパターンです *1。ただし、適応されるのは実行されたディレクトリ内だけです。したがって、fuga以下のファイル(11.html)は合致しません。 2つ目のパターンでは、「**」は「*」とほぼ同じですが、全ディレクトリに適応されます。したがって、fuga以下のファイル(11.html)も合致します。

なお、ディレクトリを絞る場合は以下のようにします。

$ hg locate --include 'glob:**fuga**.html'
fuga/11.html

次に、「.html」と「.php」を含むファイルのみを表示させます。

$ hg locate --include 'glob:**.{html,php}'
1.html
1.php
2.html
2.php
3.html
3.php
fuga/11.html
fuga/12.php

「{...,...}」というパターンになりましたが、この中に含まれている文字列がいずれかが合致すれば、全体が合致させるパターンです。条件分岐でいうと「OR」みたいなものですね。

次は、拡張子が2文字のファイルを表示させます。

$ hg locate --include 'glob:**.??'
fuga/13.js

「?」は単一の文字に合致させるパターンです。この場合、「??」なので任意も2文字なら何でも合致します。

excludeを使うには

includeと同じなので省略します(笑)。

参考URL

*1:bash等でよく使いますね