コマンド置換 (command substitution) 入門 — $(...) でコマンド結果を変数に取り込む
この記事で学べること
- コマンド置換 という考え方が分かる
$(コマンド)で 実行結果を変数に取り込む 方法が分かる- 古い書き方の バッククォート
...との違いが分かる - なぜ
"$(...)"と クォートで囲む のかが分かる
結論(先に覚えるべき型)
- コマンドの結果を 変数に入れる →
VAR=$(コマンド) - 結果を 文章に埋め込む →
echo "今日は $(date)" - 迷ったら
"$(...)"とダブルクォートで囲む
1. コマンド置換とは何か?
結論: コマンド置換はコマンドの実行結果を、その場の文字列として埋め込む仕組み。
$(...)で書く。
date を実行すると今日の日付が出ますよね。あの結果を別のコマンドの中で使いたいんですけど、どうすればいいですか?$(コマンド) と書くと、その部分が コマンドの実行結果に置き換わる んだ。$(date) と書くと、シェルは先に date を実行して、その出力で $(date) を丸ごと差し替えてからコマンド全体を実行するんだ。$ echo "今日は $(date) です"
今日は 2026年 6月 5日 金曜日 12:00:00 JST です
置き換えのイメージ
echo "今日は $(date) です"
↓ date を先に実行
echo "今日は 2026年 6月 5日 ... です"$(...) の中身が 実行結果という名の文字列 に化けてから、外側のコマンドが動く。
2. 結果を変数に取り込む
結論:
VAR=$(コマンド)でコマンドの出力を変数に保存できる。=の前後にスペースを入れないのが鉄則。
2-1. 基本形
$ today=$(date +%Y-%m-%d) $ echo "$today"
2026-06-05
today という変数に日付が入りましたね! これは便利。$ logfile="backup-$today.log" $ echo "$logfile"
backup-2026-06-05.log
2-2. = の前後にスペースを入れない
変数代入は = の前後にスペースを入れてはいけない。
today = $(date) # NG: today というコマンドを探しに行ってエラー today=$(date) # OK
スペースを入れると、シェルは today を コマンド名 だと解釈してしまう。
3. バッククォートとの違い
結論: 古い書き方の
`...`でも同じ動作。しかし入れ子や可読性で不利なため、今は$(...)を使う。
`date` みたいにバッククォートで囲んでいる記事もありました。あれは何ですか?$(date) とほぼ同じだよ。ただ今は $(...) を使うのが推奨なんだ。# 古い書き方(バッククォート) $ echo "今日は `date` です" # 新しい書き方(推奨) $ echo "今日は $(date) です"
$(...) が推奨される理由
| 観点 | バッククォート ... |
$(...) |
|---|---|---|
| 入れ子 | 書きにくい(要エスケープ) | そのまま書ける |
| 見やすさ | 縦棒と紛らわしい | 括弧で明確 |
| 引用符の扱い | クセがある | 素直 |
バッククォートは「読めればOK」。自分で書くときは $(...) に統一 しよう。
4. 入れ子(ネスト)で組み合わせる
結論:
$(...)は中にさらに$(...)を書ける。内側から順に実行され、結果が外側へ渡る。
$ echo "$(basename $(pwd))"
myproject
$(...) の中にまた $(...) がありますね。これはどう動くんですか?$(pwd) が現在のパス(例: /home/user/myproject)になって、それを basename が受け取って末尾の myproject だけ取り出すんだ。内側から外側への流れ
basename $(pwd)
↓ pwd を実行
basename /home/user/myproject
↓ basename を実行
myprojectバッククォートだと内側を \` とエスケープする必要があり面倒。$(...) なら そのまま入れ子にできる のが強み。
5. クォートで囲む理由
結論:
"$(...)"とダブルクォートで囲むと、結果に空白や改行があっても 1 つの値として安全に扱える。
5-1. クォートしないと起きる事故
$ files=$(ls) $ echo $files # クォートなし
$(...) の結果はスペースや改行で バラバラの単語に分割 されてしまうんだ(単語分割という)。改行や空白をそのまま保ちたいときは、ダブルクォートで囲む。$ echo "$files" # クォートあり
Documents Downloads report.txt
5-2. 迷ったら囲む
コマンド置換の結果は 基本的に "$(...)" とダブルクォートで囲む。
- ファイル名にスペースが含まれていても壊れない
- 改行が保たれる
- 空の結果でも引数が消えてエラーになるのを防げる
「とりあえず囲んでおく」で事故の大半を防げる。
6. よくある初心者のつまずき
結論: 末尾の改行は自動で消える、
$()の中でも変数は使える、の 2 点を押さえると混乱しにくい。
6-1. 末尾の改行は取り除かれる
$ count=$(ls | wc -l) $ echo "ファイル数は $count 個"
ファイル数は 3 個
コマンド置換は 出力末尾の改行を自動的に取り除く。だから上のように数値をそのまま文章へ埋め込める。
6-2. $() の中でも変数や引数が使える
$ dir=/etc $ echo "$dir のファイル数: $(ls "$dir" | wc -l)"
/etc のファイル数: 220
$(...) の中は 普通のコマンドラインと同じ。変数も、パイプも、別のコマンド置換も自由に書ける。
6-3. 結果が空でも壊れないようにする
$ result="$(grep "存在しない語" file.txt)" $ echo "[$result]"
[]
クォートで囲んでいれば、検索結果が空でも [] と表示されるだけで済む。クォートを外すと引数そのものが消え、思わぬ動作の原因になる。
7. ミニ課題:実際にやってみよう
結論: 変数代入・文章への埋め込み・入れ子の 3 問で、コマンド置換の基本を手で確かめる。
課題1: 現在のユーザー名を me という変数に入れて表示しよう(whoami を使う)。
ヒントを見る
変数名=$(コマンド) の形。表示は echo "$変数名"。
解答例
$ me=$(whoami) $ echo "私は $me です"
課題2: 「現在のディレクトリは ◯◯ です」という文章を、pwd の結果を埋め込んで表示しよう。
ヒントを見る
echo "... $(pwd) ..." の形で、ダブルクォートで囲む。
解答例
$ echo "現在のディレクトリは $(pwd) です"
課題3: 今いるディレクトリの 名前だけ(パス全体ではなく末尾)を表示しよう(入れ子を使う)。
ヒントを見る
basename に $(pwd) を渡す。$(basename "$(pwd)") の形。
解答例
$ echo "$(basename "$(pwd)")"
pwd で取得したパスの末尾だけを basename が取り出す。
8. コピペ用テンプレート
結論: 代入・埋め込み・ファイル名生成・カウントのよく使う型をまとめて手元に置いておく。
よく使う型をまとめておく
# 結果を変数に入れる VAR=$(コマンド) # 文章に埋め込む(必ずダブルクォート) echo "結果は $(コマンド) です" # 日付入りのファイル名を作る logfile="app-$(date +%Y%m%d).log" # 行数を数えて変数に count=$(ls | wc -l) # 入れ子で組み合わせる name="$(basename "$(pwd)")"