「bashで *.log って書くとなんで複数ファイルが消せるのか、原理を知っておきたい」
シェルのメタキャラクタ(ワイルドカード)は、bashでファイル名のパターンを表現する特殊な記号です。
*、?、[]、{} などを正しく使い分けると、何百ファイルあっても1コマンドで扱えるようになります。
この記事では、bashのメタキャラクタの基本(* ? [] {})から、エスケープの書き方、find・rm・cpとの組み合わせ、ドットファイルの罠、shoptで挙動を変える方法までを、現役のサーバー管理者目線で解説します。
この記事のポイント
・メタキャラクタは bash がファイル名展開(glob)に使うワイルドカード
・* は0文字以上、? は任意1文字、[] は文字集合、{} は文字列生成
・特殊な意味を打ち消すにはバックスラッシュ \ かシングルクォート で囲む
・ドットファイルは * にマッチしない、shopt -s dotglob で含められる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
シェルのメタキャラクタとは何か(bashのファイル名展開の仕組み)
メタキャラクタとは、bashなどのシェルが「ファイル名のパターン」を表現するために用意した特殊な記号のことです。ワイルドカード(wildcard)、グロブ(glob)と呼ばれることもあり、どれもほぼ同じ意味で使われます。
重要なのは「メタキャラクタを解釈しているのはコマンドではなくシェル本体(bash)」という点です。
たとえば
rm *.log と打つと、bashが先に *.log を実体のファイル名リスト(a.log b.log c.log…)に展開し、rmコマンドにはその展開後のファイル名が引数として渡されます。これを「ファイル名展開(pathname expansion)」と呼びます。
カレントディレクトリに次のファイルがあるとします。
$ ls a.txt aaa b.txt bbb c.txt ccc
ls *.txt を実行すると、bashが *.txt を「a.txt b.txt c.txt」に展開してから ls に渡します。$ ls *.txt a.txt b.txt c.txt $ ls a* a.txt aaa
$ ls *.xyz ls: '*.xyz' にアクセスできません: そのようなファイルやディレクトリはありません
shopt -s nullglob でマッチゼロ時を空文字列に変えられます。スクリプトで「マッチがなければ何もしない」処理にしたい時に有用です。
bashで使える主なメタキャラクタ(* ? [] {})
bashで日常的に使うメタキャラクタは、大きく分けて * ? [] {} の4種類です。それぞれ役割が違うので、一気に覚えるより「いつ使うか」のセットで覚えるのが近道です。
1. アスタリスク *(0文字以上の任意の文字列)
*(アスタリスク)は0文字以上の任意の文字列にマッチします。「特に0文字にもマッチする」という点が落とし穴です。たとえば「a*」は a、aa、abc、aaaa すべてにマッチします。
「*.log」はすべての .log ファイル、「2026-*.txt」は2026年で始まる日付ファイル名にマッチします。
$ ls /var/log/*.log /var/log/cron.log /var/log/messages.log /var/log/secure.log # 0文字にもマッチするため、ファイル名「a」自体も「a*」に含まれる $ ls a* a.txt aaa
2. クエスチョン ?(任意の1文字)
?(クエスチョン)は任意の1文字にマッチします。0文字にはマッチしません。「a?」は aa や a2 にマッチしますが、「a」単体や「abc」にはマッチしません。
ログのローテーション番号が1桁の時など、文字数を絞り込みたい時に使います。
$ ls access.log.? access.log.1 access.log.2 access.log.9
3. ブラケット [](文字集合・範囲指定)
[] は、その中に列挙した文字のいずれか「1文字」にマッチします。範囲指定は「-」、否定は先頭の「!」または「^」で表現します。
・[abc]:a、b、cのいずれか1文字
・[a-z]:アルファベット小文字1文字
・[0-9]:数字1文字
・[!a-z]:アルファベット小文字以外の1文字
# 数字で終わる .log ファイルだけ $ ls *.log.[0-9] access.log.1 access.log.2 # 「a」「b」「c」で始まる .txt $ ls [abc].txt a.txt b.txt c.txt
4. ブレース {}(文字列の生成)
{} は、これまでの3つと少し性質が違います。* ? [] が「既にあるファイル名にマッチさせる」ためのワイルドカードであるのに対し、{} は「文字列を生成する」ための展開です(ブレース展開、brace expansion)。
「text{1,2}」は「text1」「text2」の2つに展開されます。実在しないファイル名も生成するので、touch・mkdir・cp との組み合わせが定番です。
# 連番ディレクトリを一括作成 $ mkdir log_{2024,2025,2026} $ ls -d log_* log_2024 log_2025 log_2026 # 範囲指定もできる $ touch file_{1..5}.txt $ ls file_*.txt file_1.txt file_2.txt file_3.txt file_4.txt file_5.txt # 設定ファイルのバックアップでよく使うパターン $ cp /etc/nginx/nginx.conf{,.bak}
メタキャラクタをエスケープする方法(特殊な意味を打ち消す)
*、?、[、{ などをファイル名の一部として「文字そのまま」扱いたい時は、特殊な意味を打ち消す必要があります。方法は3つあります。
1. バックスラッシュ \ でエスケープ
直前にバックスラッシュ \ を付けると、その1文字だけがエスケープされます。$ ls * a.txt aaa b.txt bbb c.txt ccc # 「*」というファイル名を作る $ touch \* # 「*」というファイルだけを表示 $ ls \* *
2. シングルクォート で囲む(最も安全)
シングルクォートで囲んだ文字列の中では、メタキャラクタを含むすべての特殊文字が無効化されます。スクリプトで「ユーザー入力をそのまま安全に渡したい」時の鉄則は、シングルクォートで囲むことです。
# *.txt をメタキャラクタとして展開せず文字列として扱う $ echo '*.txt' *.txt # ダブルクォートだと変数展開は効くが、グロブ展開は止まる $ echo "*.txt" *.txt
3. ダブルクォート " で囲む(変数は展開される)
ダブルクォートでもメタキャラクタの展開は止まりますが、シェル変数の$VAR や $(command) は展開されます。「変数は展開してほしい、でもグロブは止めたい」時に使い分けます。
find・rm・cpとの組み合わせと注意点
メタキャラクタは ls だけでなく、ファイル操作系のコマンド全般で使えます。便利な反面、現場では「うっかり全消し」事故も多発します。1. rm で *.log を消す時の鉄則
ログを掃除する時にrm *.log を打つ前に、必ず ls で展開結果を確認します。# まず ls で展開結果を確認 $ ls *.log access.log cron.log error.log # 問題なければ rm $ rm *.log # 確認ダイアログを出して安全にやる $ rm -i *.log
類似の事故として
rm -rf / tmp/*(/ と tmp の間にスペース)も知られています。
2. find と組み合わせる時はクォートする
findの-nameオプションにメタキャラクタを渡す時は、必ずシングルクォートで囲みます。クォートしないとbashが先に展開してしまい、findの動作が意図と変わります。
# 正解:findにパターンをそのまま渡す $ find /var/log -name '*.log' -mtime +30 -delete # 間違い:bashが先に *.log を展開してしまう $ find /var/log -name *.log -mtime +30
3. cp と {} で安全にバックアップ
本番サーバーで設定ファイルを編集する前、{} を使った同名バックアップが定番です。# 日付付きバックアップを一発で $ cp /etc/httpd/conf/httpd.conf{,.$(date +%Y%m%d)} $ ls /etc/httpd/conf/ httpd.conf httpd.conf.20260518
ドットファイル(.bashrc等)の罠とshopt dotglob
bashのデフォルトでは、* はドット(.)で始まるファイルにマッチしません。これは「隠しファイルを誤って一括処理しないように」という安全設計ですが、知らないとバックアップ漏れの原因になります。
# .bashrc などのドットファイルは * に含まれない $ ls file1 file2 $ ls -a . .. .bashrc .ssh file1 file2 $ ls * file1 file2 # ドットファイルも含めたい時は shopt -s dotglob $ shopt -s dotglob $ ls * .bashrc .ssh file1 file2 # 元に戻す $ shopt -u dotglob
逆にスクリプトの冒頭で
shopt -s nullglob を有効にしておくと、マッチゼロ時の挙動が安全になり、forループでファイルが存在しない時に変なパターン文字列が渡される事故を防げます。
「No match」「そのようなファイルやディレクトリはありません」が出た時の対処法
メタキャラクタを使うと頻繁に出るエラーが「No match」「No such file or directory」です。原因は3パターンに大別できます。
1. ファイルが本当に存在しない
最も多いケース。ls -la で実際のファイル一覧を確認します。$ ls *.log ls: '*.log' にアクセスできません: そのようなファイルやディレクトリはありません # 存在チェック $ ls -la | grep log
2. パターンが意図と違う
たとえば「access.log.[0-9]」のつもりで「access.log.[1-9]」と書いていてゼロ番のログだけ拾えていない、というケース。echoで展開結果を確認するのが早道です。$ echo *.log.[0-9] access.log.1 access.log.2 cron.log.3
3. 隠しファイルだけマッチしていない
ドットで始まるファイルは * では拾えません。shopt -s dotglob で拾うか、明示的に .* と分けて指定します。本記事のまとめ
bashのメタキャラクタ(ワイルドカード)を使いこなせるかどうかで、サーバー管理の生産性は大きく変わります。「複数ファイルを一括で扱う」「設定ファイルをバックアップする」「ログを一気に整理する」など、現場では毎日のように使う機能です。ポイントは「bashが展開してからコマンドに渡している」という仕組みを正しく理解することです。これを押さえれば、エスケープも find との組み合わせも、迷わず使えるようになります。
| やりたいこと | コマンド |
|---|---|
| カレントの .txt を一覧 | ls *.txt |
| 1桁数字で終わるログを一覧 | ls access.log.[0-9] |
| 連番ディレクトリを作る | mkdir log_{2024..2026} |
| 同名バックアップを取る | cp nginx.conf{,.bak} |
| 「*」を文字として扱う | ls \* または ls '*' |
| 30日以上前の .log を一括削除 | find /var/log -name '*.log' -mtime +30 -delete |
| ドットファイルも * に含める | shopt -s dotglob |
| マッチゼロ時を空に | shopt -s nullglob |
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
登録10秒/合わなければ解除3秒 / 詳細はこちら
- 次のページへ:リダイレクトの使い方|>・>>・<・2>&1・/dev/nullの全パターン実践例
- 前のページへ:引用符|Bashのシングル・ダブル・バッククォート・ヒアドキュメントの使い分け
- この記事の属するカテゴリ:【Linux入門】初心者のための基礎知識・講座へ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は1分、解除もいつでも可。
登録無料・いつでも解除できます