locate
ファイル名データベースからパターンに合うファイルパスを表示します。
$ whatis locate
locate (1) - ファイル名データベースからパターンに合うものを表示する
$ locate --version
mlocate 0.26
$ Copyright (C) 2007 Red Hat, Inc. All rights reserved.
このソフトウェアは GPL v.2 に基づいて提供されています。
このプログラムは法律が許す範囲で無保証で提供されます。
locateのインストール
大抵のLinux ディストロにはデフォルトで入っています。
Archlinuxではmlocateパッケージをインストールすることで使えます。
$ sudo pacman -S mlocate
ファイルパスを高速検索する
$ locate some_keyword
でsome_keyword
を含むパスを表示します。
私の環境では検索にかかる時間は、保存ハードウェアSSD上に29万件の登録があるデータベースで0.4秒くらい、保存ハードウェアHDD上に450万件の登録があるデータベースで13秒くらいです。
デフォルトでは/var/lib/mlocate/mlocate.db
から検索します。
dbファイルの作り方は後述するupdatedbに記述します。
locate オプション
$ locate --help
Usage: locate [OPTION]... [PATTERN]...
Search for entries in a mlocate database.
-A, --all only print entries that match all patterns
-b, --basename match only the base name of path names
-c, --count only print number of found entries
-d, --database DBPATH use DBPATH instead of default database (which is
/var/lib/mlocate/mlocate.db)
-e, --existing only print entries for currently existing files
-L, --follow follow trailing symbolic links when checking file
existence (default)
-h, --help print this help
-i, --ignore-case ignore case distinctions when matching patterns
-l, --limit, -n LIMIT limit output (or counting) to LIMIT entries
-m, --mmap ignored, for backward compatibility
-P, --nofollow, -H don't follow trailing symbolic links when checking file
existence
-0, --null separate entries with NUL on output
-S, --statistics don't search for entries, print statistics about each
used database
-q, --quiet report no error messages about reading databases
-r, --regexp REGEXP search for basic regexp REGEXP instead of patterns
--regex patterns are extended regexps
-s, --stdio ignored, for backward compatibility
-V, --version print version information
-w, --wholename match whole path name (default)
よく使うオプションを表に記載します。
オプション | 役割 |
---|---|
-c, --count | マッチしたファイルの数だけを表示する。 |
-d, --database DBPATH | デフォルトの/var/mlocate/mlocate.db以外のデータベースを検索する。 |
-e, --existing | dbにあるけれども、実際のファイルシステム上に存在するファイルしか表示しない。 |
-i, --ignore-case | 大文字小文字無視 |
-l, --limit, -n LIMIT | 表示数をLIMIT件に抑える。 |
-r, --regexp REGEXP | 正規表現で検索する |
--regex REGEXP | 拡張正規表現で検索する |
-S, --statistics | ファイル数、ディレクトリ数などの統計情報を表示する |
異なるデータベースファイルから検索する
$ locate -d /var/lib/mlocate/mymlocate.db
でデフォルトの/var/lib/mlocate/mlocate.db
以外のデータベースファイルから検索します。
複数のデータベースファイルから検索する
$ locate -d /var/lib/mlocate/mymlocate1.db -d /var/lib/mlocate/mymlocate2.db key_word
のように-dオプションを複数使います。
または
$ locate -d /var/lib/mlocate/mymlocate1.db:/var/lib/mlocate/mymlocate2.db key_word
のように複数のデータベースファイルをコロンで区切ります。
複数のデータベースファイルから検索する(環境変数を使う)
コロンによって区切られた検索するデータベースのリストを環境変数LOCATE_PATH
として指定しておくと、-d
オプションをデフォルトで指定していることと同様に動作します。
$ export LOCATE_PATH='/var/lib/mlocate/mymlocate.db:/var/lib/mlocate/mlocate.db'
$ locate key_word
複数のデータベースファイルから検索するときはLOCATE_PATH
にコロン区切りでdbファイルを列挙していきます。
LOCATE_PATH
をディレクトリ以下全てのファイルとして指定する
LOCATE_PATH
を/var/lib/mlocate以下全てのファイルとするシェルスクリプトを紹介します。
以前までtr
とsed
を使う方法で/var/lib/mlocate以下のdbファイル名を結合していましたが、paste
コマンドを使うともっと簡単になります。
参考: シェルスクリプトの中でjoin()とsplit()相当の事をやる
$ export LOCATE_PATH=$(paste -sd: <(find /var/lib/mlocate -name '*.db'))
# OR
$ export LOCATE_PATH=$(find /var/lib/mlocate -name '*.db' | paste -sd: -)
paste
コマンドのオプション-s
で列結合から行結合に変更し、-d :
でコロンで結合します。
上のスクリプトはpasteコマンドにリダイレクション<
を使ってfind
の結果を流し込み、下のスクリプトはパイプを使ってpaste
の標準入力-
にfind
の結果を流し込みます。
結果は同じなのでお好みで選んでください。
マルチプロセスでlocate検索する
locate
コマンドは高速に(数ミリ秒以内)にファイルを検索してくれるので速さに対しては大抵満足いっているのですが、SSDではなくHDDに保存された400万件超のファイルパスを検索するときは検索に10秒以上かかっているのでイライラが溜まってきます。
検索に10秒かかってもlocate
は古いコマンドなのでシングルスレッド動作です。いまどきシングルスレッドで動いているシステムは化石なので、スレッドを複数使って高速化を図りたいと自然に思うようになってきます。
大抵のLinuxディストロのデフォルトでマルチプロセスにコマンドを実行できる機能がついています。それがxargs
コマンドです。
locate
コマンドが検索するデータベースファイルが複数ある場合に限り、データベース一つ一つに対してxargs
がlocate
コマンドの検索先を振り分けてくれます。
$ find /var/lib/mlocate -name '*.db' | xargs -P2 -I@ locate -d @ 'some_keyword'
上のシェルスクリプトと同様にしてfind ...
で見つけ出したdbファイル全てに対してxargs
が並列にコマンドを実行してくれます。
xargs
のオプション-P2
で2スレッドで並列処理を実行します。実行環境のCPUのコア数、スレッド数を超えない数値を指定しましょう。 -P0で自動的に出来る限り多くのプロセスを同時に実行しようとします。(man xargs
を読んでください。)
-I@
で@の位置にfind...
の結果、すなわちデータベースのパスを埋め込みます。
locateコマンドが'some_keyword'を含むパスをデータベースファイルから探して表示します。
$ # シングルスレッド
$ timeit locate -d $(find /var/lib/mlocate -name '*.db' | tr "\n" : | sed -e 's/:$//g') --regex 'usr.*\d+.*f'
0.35s user 0.02s system 97% cpu 0.378 total
0.35s user 0.01s system 99% cpu 0.363 total
0.37s user 0.00s system 99% cpu 0.375 total
$ # マルチスレッド
$ timeit find /var/lib/mlocate -name '*.db' | xargs -P2 -I@ locate -d @ --regex 'usr.*\d+.*f'
0.01s user 0.00s system 96% cpu 0.009 total
0.00s user 0.00s system 95% cpu 0.009 total
0.01s user 0.00s system 95% cpu 0.009 total
timeitコマンドは実行時間を3回計測する自作shell functionです。
#!/usr/bin/zsh
# shell scriptを3回実行し、実行時間を表示
# USAGE:
# timeit [command] <args>
function timeit() {
for i ($(seq 3)) time sh -c "$*" > /dev/null 2>&1
}
統計情報
検索データベースに登録したファイル数などを表示します。
-dオプションで統計情報を表示するデータベースを選択できます。
LOCATE_PATH
に複数のデータベースがあればすべてのデータベースの情報を表示します。
$ locate -S
データベース /var/lib/mlocate/mlocate.db:
95,256 辞書
866,720 ファイル
ファイル名に 91,967,343 バイト
データベースに保存するのに 27,641,702 バイト使いました
正規表現で検索する
regexpは正規表現、regexオプションは拡張正規表現を使用して検索できます。
ERE | BRE | 用途 | 代替表現 |
---|---|---|---|
| | unsupported | OR 表現 | I don’t know |
+ | unsupported | 1文字以上の繰り返し | {1,} |
? | unsupported | 0 or 1文字 | {,1} |
() | () | グループ化 | – |
{n,m} | {n,m} | n文字以上、m文字以下の繰り返し | – |
AND検索
$ locate --regex 'document.*gz'
documentの後にgzが含まれるファイルを検索します。
gzの後にdocumentが含まれるファイルは検索されないので、「documentかつgzが含まれるファイルを検索する」わけではありません。
OR検索
$ locate --regex 'document|gz'
documentまたはgzが含まれるファイルを検索します。
NOT検索
$ locate document | grep -v gz
locate
オプションだけでできませんが、grep -v
を併用することで、「documentは含まれるが、gzは含まれないファイル」の検索ができます。
updatedb
locate
で検索するデータベースファイル(.db)を作成、更新します。
updatedb
により作成されるデータベースファイルは、ファイルパスのリスト情報が記されたバイナリファイルです。
大抵/var/lib/mlocate下に作成されるため、updatedbコマンドを使用するときはroot権限が必要です。
この記事では
updatedb
をroot権限で実行するとして、sudoコマンドは省略して記載します。
- dbファイルを事前に作成しておかないと検索されません。
- dbファイルを事前に更新しておかないと古いファイルが検索されます。
- 例えばdbファイルを作成した後に/home/hoge/attatchment.tar.gzを作成すると、存在するはずの/home/hoge/attatchment.tar.gzが検索結果に出てきません。
- 例えばdbファイルを作成した後に/home/hoge/document.txtを削除すると、消されて存在しなくなったはずの/home/hoge/document.txtが検索結果に出てきます。
$ whatis updatedb
updatedb (1) - ファイル名データベースを更新する
$ updatedb --version
updatedb (mlocate) 0.26
Copyright (C) 2007 Red Hat, Inc. All rights reserved.
このソフトウェアは GPL v.2 に基づいて提供されています。
このプログラムは法律が許す範囲で無保証で提供されます。
updatedb オプション
$ updatedb --help
利用方法: updatedb [オプション]...
mlocate データベースを更新します。
-f, --add-prunefs FS 同じ FS を除外する
-n, --add-prunenames NAMES 同じ NAMES を除外する
-e, --add-prunepaths PATHS 同じ PATHS を除外する
-U, --database-root PATH データベース中の保存するサブツリー (省略値 "/")
-h, --help このヘルプを印刷する
-o, --output FILE 更新するデータベース (省略値
`/var/lib/mlocate/mlocate.db')
--prune-bind-mounts FLAG bind マウントを除外する (省略値 "no")
--prunefs FS データベースから除外するファイルシステム
--prunenames NAMES データベースから除外する辞書名
--prunepaths PATHS データベースから除外するパス
-l, --require-visibility FLAG ファイルを報告する前に可視性をチェックする
(デフォルト値 "yes")
-v, --verbose 見つかったファイルのバスを印刷する
-V, --version バージョン情報を印刷する
設定はファイル`/etc/updatedb.conf'
から読み込んだ値を省略値とします。
バグを https://pagure.io/mlocate へ報告してください。
マウントしたドライブの検索データベースを作成する
updatedbはmntしたドライブを使ってデータベースを作成しないので、 次のようにして別ドライブのパスをデータベースに含めます。
(Linux環境ではmntも含まれていましたが、Windosホストの仮想マシンでcronすると共有ドライブを/mntにマウントしたところがデータベースに含まれませんでした。システム管理者じゃないので詳しくはわからないのですがWindowsの共有ドライブ機能かレイドを組んでバックアップしていることが関係してそうです。)
$ updatedb -U /mnt/z --output /var/lib/mlocate/another.db
上のコマンドは/mnt/z以下のファイルを検索データベースを/var/lib/mlocate/another.dbに出力します。
更にlocate
検索するときは-d
オプションを使ってanother.dbを指定するか、LOCATE_PATH
にanother.dbを含めます。
--output
を省略すると/var/lib/mlocate/mlocate.dbに出力されます。
cron
定期的にコマンドを実行するデーモンを立ち上げます。
$ whatis cron
cron (8) - 予定されたコマンドを実行するデーモン...
先述の通り、locate
検索前にupdatedb
コマンドを打ってデータベースを最新の状態にしておかないと、存在するはずのパスが検索結果に出てこなかったり、過去に存在したファイルパスが検索結果に出てきてしまいます。
そのため、updatedb
は定期的に実行しておく必要があり、大抵のLinuxディストリビューションではcron
により設定済みです。
まとめ
- locateコマンドは高速ファイルパス検索コマンドです。
- locate検索するときにはupdatedbコマンドにより検索データベースを作る前準備が必要です。
- データベースコマンドは定期的に作成しておくべきで、cronデーモンを利用することが主流です。