14.4.7 複数ファイルの指定・ファイルの検索

この節では複数ファイルの指定方法と,ファイルの検索の方法について説明します.

複数ファイルの指定

これまで説明してきたいろいろなファイル操作のコマンドは,複数のファイルをいっぺんに処理対象にすることができます.そのためには,ファイル名やディレクトリ名のところに以下のような特殊文字を使います.これらの特殊文字をワイルドカードといいます.

*(アスタリスク)
0 文字以上のあらゆる文字列を意味します.
?(疑問符)
任意の 1 文字を意味します.
[文字列]
[ ] 内にある文字の中のどれか 1 文字,を意味します.例えば [abc] は a, b, c のどれかという意味です.
また,[a-z] と書くと,a から z までのうちのどれか 1 文字,を意味します.
[!文字列]
すぐ上の [文字列] と反対に,[ ] に含まれない 1 文字を意味します.例えば,
[!a-y] は,a〜y でない 1 文字(例えば,大文字,数字や小文字のz)を意味します.
{文字列 1, 文字列 2, …}
カンマで区切って並べられた文字列のどれか 1 つを意味します.

以下にいくつかの例を載せます(面倒なので,このページではディレクトリのことも単にファイルとよぶことにします).

*       (名前が . で始まらないような)任意のファイル
.*      名前が . で始まる隠しファイル全て
*ro*    名前の中に ro を含むファイル全て
[a-s]*  名前の最初の文字が a から s であるファイル全て
g?b     1文字目が g,3文字目が b であるような3文字のファイルすべて
[A-Za]* 名前の最初の文字が大文字か a であるようなファイル全て
*.tex   拡張子が .tex であるファイル全て
*~      最後が ~ で終わるファイル全て

但し, * だけ単独で指定しても,名前が . で始まる隠しファイルは対象になりません.

使い方の例

UNIX 系 OS でよく使われるエディタ Emacs(hwb8.4 Emacs  参照)は,名前が ~ で終わるバックアップファイルを大量に作ります.それらを表示するには,次のように書きます.

ls *~return2

これらのバックアップファイルは.間違って上書き保存したときのことを考えると便利ですが,かといってあまりありすぎるのも考えものです.これらを全部削除するには,次のようにします.
rm -i *~return2

ここで rm コマンドに -i オプションをつけているのは,ひとつひとつ本当に消してよいか尋ねてくれるからです.このオプションにより,間違いで一気にファイルを消してしまうことを防げます.間違えて「rm -i * ~」と入力したのに気づかないで enter を押してしまった場合に,確認メッセージのおかげで大惨事を免れることができます.
このようにワイルドカードは便利ですが,少し間違えるだけで大変なことになってしまいますので,使用には十分注意を払って下さい.

ワイルドカードの正確な意味

ワイルドカードの正確な意味は,「指定したパターンにマッチするファイル名の集合を持ってきて,その中身をパターンを書いた位置に展開する」ということです.
echo コマンドで,その展開の様子を確認することができます.次の入力と出力を例にとって説明します.

echo *.texreturn2
bib.tex main.tex report.tex test.tex tmp.tex

  1. まず,入力の *.tex の部分がシェル(hwb25. シェルの活用)によって展開され,入力したコマンドは次のように内部で書き換えられます.
    echo bib.tex main.tex report.tex test.tex tmp.tex
  2. その後,このコマンドが実際に実行されます.echo コマンドは単に後に続く文字列を出力するだけですから,結果として上に述べたようになるわけです.

ファイルの検索

コマンドライン上からファイルを検索するには,find コマンドlocate コマンドを使うのが便利です.find コマンドの方が高機能で,locate コマンドは(あらかじめ作られたファイル名のデータベースから検索するので)高速・簡便です.教育用計算機システムではなぜか locate コマンドが正しく動かないので,find コマンドのみ説明します.
find コマンドは,引数に検索対象のディレクトリと検索オプションを指定します.一番簡単な例は,「.(カレントディレクトリ)以下のファイルを全部表示する」ものです.

find .return2
. ./base ./base/00readme.txt ./base/alltt.dtx (後略)

この節の残りでは.検索対象のディレクトリの後に指定するオプションについて説明していきます.

検索条件の指定

まず -name オプションは,検索するファイルの名称を指定するものです.下の例では名前が 00readme.txt であるファイルや,alltt.* であるようなファイルを検索しています.

find base -name 00readme.txtreturn2
base/00readme.txt
find base -name "alltt.*"return2
base/alltt.dtx base/alltt.ins

このように,条件にワイルドカードを指定する場合は ” ” でくくる必要があります.そうでないと,先にシェルによって展開されてしまうからです.
通常のファイルやディレクトリ,あるいはシンボリックリンクのみ検索したいような場合には -type オプションを指定します.-type の後には次のどれかが指定できます.

b, c, p, s
   スペシャルファイルやソケットなどの特殊なファイルです.ここでは説明しません.
d  ディレクトリ
l  シンボリックリンク
f  上のどれでもない「通常のファイル」

例えば,次はディレクトリのみを検索します.

find . -type dreturn2
. ./base ./doc

ファイルの更新日時によって検索するには -mtime オプションを使います.-mtime オプションには,対象とする範囲を指定します.

-mtime -45   45日前より後に更新されたファイル
-mtime +365 365日前より前に更新されたファイル
-mtime  0     0日前に更新されたファイル

なお,ここでいう「何日前」では,現在時刻との差の 24 時間未満の半端は切り上げられます.そのため

  • -mtime 0 は「この 24 時間内に更新されたファイル」
  • -mtime +0 は「24 時間より前に更新されたファイル」
  • -mtime -2 は「48 時間前より最近に更新されたファイル」

ということになります.似たようなものに -atime(最終アクセス日時),-ctime(パーミッションなどステータスの変更日時)などのオプションがあり,-mtime と同じように使うことができますます.
他にも,所有者や所有しているグループ,ファイルサイズなども条件に加えることができます.

検索条件の演算

複数の検索条件を同時に指定して検索することもできます.例を挙げて説明します.
「名前が a から g で始まり末尾が .pdf で終わるファイル」と,「名前が a で始まるファイル」はそれぞれ以下で検索することができます.

find . -name "[a-g]*.pdf"return2
./classes.pdf (後略)
find . -name "a*"return2
./alltt.pdf ./alltt.log (後略)

これらのオプションを続けて指定すると,両方の条件にマッチするファイルを検索することになります.2 つの条件を -a オプションでつなげても同じです.
find . -name "[a-g]*.pdf" -name "a*"return2
./alltt.pdf

一方,両者を -o オプションで繋げると,少なくともどちらか片方にマッチするファイルを検索します.
find . -name "[a-g]*.pdf" -o -name "a*"return2
./classes.pdf ./alltt.pdf ./alltt.log (後略)

また,条件を否定するには否定する条件の前に ! をつけます.ただ実際にコマンドラインで入力するときには \! としないとエラーが起こる可能性があるので,注意してください.次の例では,名前が .ins で終わらないファイルを検索します.
find . \! -name "*.ins"return2
. ./ltsect.pdf ./ltfntcmd.pdf (後略)